Skip to content

Commit 4fe709b

Browse files
committed
Move implementation code into a SwiftPM package
1 parent 36baaab commit 4fe709b

File tree

8 files changed

+105
-15
lines changed

8 files changed

+105
-15
lines changed

DebugLayout/.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.DS_Store
2+
/.build
3+
/Packages
4+
/*.xcodeproj
5+
xcuserdata/
6+
DerivedData/
7+
.swiftpm/config/registries.json
8+
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
9+
.netrc

DebugLayout/Package.swift

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// swift-tools-version: 5.7
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
6+
let package = Package(
7+
name: "DebugLayout",
8+
platforms: [.macOS(.v13), .iOS(.v16), .tvOS(.v16), .watchOS(.v9)],
9+
products: [
10+
// Products define the executables and libraries a package produces, and make them visible to other packages.
11+
.library(
12+
name: "DebugLayout",
13+
targets: ["DebugLayout"]
14+
),
15+
],
16+
dependencies: [
17+
// Dependencies declare other packages that this package depends on.
18+
// .package(url: /* package url */, from: "1.0.0"),
19+
],
20+
targets: [
21+
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
22+
// Targets can depend on other targets in this package, and on products in packages this package depends on.
23+
.target(
24+
name: "DebugLayout",
25+
dependencies: []
26+
),
27+
.testTarget(
28+
name: "DebugLayoutTests",
29+
dependencies: ["DebugLayout"]
30+
),
31+
]
32+
)

DebugLayout/README.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# DebugLayout
2+
3+
Ole Begemann, 2022-09
4+
5+
Based on: [objc.io, Swift Talk episode 318, Inspecting SwiftUI's Layout Process (2022-08)](https://talk.objc.io/episodes/S01E318-inspecting-swiftui-s-layout-process)
6+
7+
Inspect the layout algorithm of SwiftUI views, i.e. what sizes views propose to
8+
their children and what sizes they return to their parents.
9+
10+
## Requirements
11+
12+
iOS 16.0 or macOS 13.0 (requires the `Layout` protocol).
13+
14+
## Instructions
15+
16+
1. `import DebugLayout`
17+
18+
2. Add `.debugLayout()` at each point in a view tree where you want to inspect
19+
the layout algorithm (what sizes are being proposed and returned).
20+
21+
3. At the top of the view tree you want to inspect, add `.startDebugLayout()`.
22+
23+
See the README of the sample app for a complete example.

LayoutInspector/DebugLayout.swift DebugLayout/Sources/DebugLayout/DebugLayout.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,15 @@ extension View {
77
/// Start debugging the layout algorithm for this subtree.
88
///
99
/// This clears the debug layout log.
10-
func startDebugLayout(selection: String? = nil) -> some View {
10+
public func startDebugLayout(selection: String? = nil) -> some View {
1111
ClearDebugLayoutLog {
1212
self
1313
}
1414
.environment(\.debugLayoutSelectedViewID, selection)
1515
}
1616

1717
/// Monitor the layout proposals and responses for this view and add them to the log.
18-
func debugLayout(_ label: String) -> some View {
18+
public func debugLayout(_ label: String) -> some View {
1919
DebugLayout(label: label) {
2020
self
2121
}

LayoutInspector/DebugLayoutLog.swift DebugLayout/Sources/DebugLayout/DebugLayoutLog.swift

+5-5
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ struct ClearDebugLayoutLog: Layout {
5555
}
5656
}
5757

58-
final class LogStore: ObservableObject {
59-
static let shared: LogStore = .init()
58+
public final class LogStore: ObservableObject {
59+
public static let shared: LogStore = .init()
6060

6161
@Published var log: [LogItem] = []
6262
}
@@ -101,14 +101,14 @@ extension EnvironmentValues {
101101
}
102102
}
103103

104-
struct DebugLayoutLogView: View {
104+
public struct DebugLayoutLogView: View {
105105
@Binding var selection: String?
106106
@ObservedObject var logStore: LogStore
107107

108108
private static let tableRowHorizontalPadding: CGFloat = 8
109109
private static let tableRowVerticalPadding: CGFloat = 4
110110

111-
init(selection: Binding<String?>? = nil, logStore: LogStore = LogStore.shared) {
111+
public init(selection: Binding<String?>? = nil, logStore: LogStore = LogStore.shared) {
112112
if let binding = selection {
113113
self._selection = binding
114114
} else {
@@ -118,7 +118,7 @@ struct DebugLayoutLogView: View {
118118
self._logStore = ObservedObject(wrappedValue: logStore)
119119
}
120120

121-
var body: some View {
121+
public var body: some View {
122122
ScrollView(.vertical) {
123123
Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 0, verticalSpacing: 0) {
124124
// Table header row
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import XCTest
2+
@testable import DebugLayout
3+
4+
final class DebugLayoutTests: XCTestCase {
5+
func testExample() throws {
6+
// This is an example of a functional test case.
7+
// Use XCTAssert and related functions to verify your tests produce the correct
8+
// results.
9+
XCTAssertEqual(DebugLayout().text, "Hello, World!")
10+
}
11+
}

LayoutInspector.xcodeproj/project.pbxproj

+22-8
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111
5D2245F228D8FDB400E84C7D /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D2245F128D8FDB400E84C7D /* ContentView.swift */; };
1212
5D2245F428D8FDB500E84C7D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5D2245F328D8FDB500E84C7D /* Assets.xcassets */; };
1313
5D2245F828D8FDB500E84C7D /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5D2245F728D8FDB500E84C7D /* Preview Assets.xcassets */; };
14-
5D2245FF28D9015300E84C7D /* DebugLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D2245FE28D9015300E84C7D /* DebugLayout.swift */; };
15-
5D22463928DA2E7500E84C7D /* DebugLayoutLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D22463828DA2E7500E84C7D /* DebugLayoutLog.swift */; };
14+
5D8B5F7228E600FA00CF3721 /* DebugLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 5D8B5F7128E600FA00CF3721 /* DebugLayout */; };
1615
/* End PBXBuildFile section */
1716

1817
/* Begin PBXFileReference section */
@@ -22,8 +21,7 @@
2221
5D2245F328D8FDB500E84C7D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
2322
5D2245F528D8FDB500E84C7D /* LayoutInspector.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LayoutInspector.entitlements; sourceTree = "<group>"; };
2423
5D2245F728D8FDB500E84C7D /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
25-
5D2245FE28D9015300E84C7D /* DebugLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugLayout.swift; sourceTree = "<group>"; };
26-
5D22463828DA2E7500E84C7D /* DebugLayoutLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugLayoutLog.swift; sourceTree = "<group>"; };
24+
5D8B5F6F28E6003000CF3721 /* DebugLayout */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = DebugLayout; sourceTree = "<group>"; };
2725
5DB6BE4F28DE4D4E00280F5E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
2826
/* End PBXFileReference section */
2927

@@ -32,6 +30,7 @@
3230
isa = PBXFrameworksBuildPhase;
3331
buildActionMask = 2147483647;
3432
files = (
33+
5D8B5F7228E600FA00CF3721 /* DebugLayout in Frameworks */,
3534
);
3635
runOnlyForDeploymentPostprocessing = 0;
3736
};
@@ -43,7 +42,9 @@
4342
children = (
4443
5DB6BE4F28DE4D4E00280F5E /* README.md */,
4544
5D2245EE28D8FDB400E84C7D /* LayoutInspector */,
45+
5D8B5F6F28E6003000CF3721 /* DebugLayout */,
4646
5D2245ED28D8FDB400E84C7D /* Products */,
47+
5D8B5F7028E600FA00CF3721 /* Frameworks */,
4748
);
4849
indentWidth = 4;
4950
sourceTree = "<group>";
@@ -62,8 +63,6 @@
6263
children = (
6364
5D2245EF28D8FDB400E84C7D /* App.swift */,
6465
5D2245F128D8FDB400E84C7D /* ContentView.swift */,
65-
5D2245FE28D9015300E84C7D /* DebugLayout.swift */,
66-
5D22463828DA2E7500E84C7D /* DebugLayoutLog.swift */,
6766
5D2245F328D8FDB500E84C7D /* Assets.xcassets */,
6867
5D2245F528D8FDB500E84C7D /* LayoutInspector.entitlements */,
6968
5D2245F628D8FDB500E84C7D /* Preview Content */,
@@ -79,6 +78,13 @@
7978
path = "Preview Content";
8079
sourceTree = "<group>";
8180
};
81+
5D8B5F7028E600FA00CF3721 /* Frameworks */ = {
82+
isa = PBXGroup;
83+
children = (
84+
);
85+
name = Frameworks;
86+
sourceTree = "<group>";
87+
};
8288
/* End PBXGroup section */
8389

8490
/* Begin PBXNativeTarget section */
@@ -95,6 +101,9 @@
95101
dependencies = (
96102
);
97103
name = LayoutInspector;
104+
packageProductDependencies = (
105+
5D8B5F7128E600FA00CF3721 /* DebugLayout */,
106+
);
98107
productName = LayoutInspector;
99108
productReference = 5D2245EC28D8FDB400E84C7D /* LayoutInspector.app */;
100109
productType = "com.apple.product-type.application";
@@ -149,10 +158,8 @@
149158
isa = PBXSourcesBuildPhase;
150159
buildActionMask = 2147483647;
151160
files = (
152-
5D2245FF28D9015300E84C7D /* DebugLayout.swift in Sources */,
153161
5D2245F228D8FDB400E84C7D /* ContentView.swift in Sources */,
154162
5D2245F028D8FDB400E84C7D /* App.swift in Sources */,
155-
5D22463928DA2E7500E84C7D /* DebugLayoutLog.swift in Sources */,
156163
);
157164
runOnlyForDeploymentPostprocessing = 0;
158165
};
@@ -366,6 +373,13 @@
366373
defaultConfigurationName = Release;
367374
};
368375
/* End XCConfigurationList section */
376+
377+
/* Begin XCSwiftPackageProductDependency section */
378+
5D8B5F7128E600FA00CF3721 /* DebugLayout */ = {
379+
isa = XCSwiftPackageProductDependency;
380+
productName = DebugLayout;
381+
};
382+
/* End XCSwiftPackageProductDependency section */
369383
};
370384
rootObject = 5D2245E428D8FDB400E84C7D /* Project object */;
371385
}

LayoutInspector/ContentView.swift

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import SwiftUI
2+
import DebugLayout
23

34
struct ContentView: View {
45
@State private var width: CGFloat = 300

0 commit comments

Comments
 (0)