@@ -2,7 +2,8 @@ import SwiftUI
2
2
3
3
@available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
4
4
struct InspectLayout : ViewModifier {
5
- @StateObject private var logStore : LogStore = . init( )
5
+ // Don't observe LogStore. Avoids an infinite update loop.
6
+ var logStore : LogStore
6
7
@State private var selectedView : String ? = nil
7
8
@State private var generation : Int = 0
8
9
@State private var inspectorFrame : CGRect = CGRect ( x: 0 , y: 0 , width: 300 , height: 300 )
@@ -31,13 +32,12 @@ struct InspectLayout: ViewModifier {
31
32
. offset ( x: inspectorFrame. minX, y: inspectorFrame. minY)
32
33
. coordinateSpace ( name: Self . coordSpaceName)
33
34
}
34
- . environment ( \. didCallInspectLayout, true )
35
- . environmentObject ( logStore)
35
+ . environment ( \. logStore, logStore)
36
36
}
37
37
38
38
@ViewBuilder private var inspectorUI : some View {
39
39
ScrollView ( [ . vertical, . horizontal] ) {
40
- LogEntriesGrid ( logEntries : logStore. log , highlight: $selectedView)
40
+ LogEntriesGrid ( logStore : logStore, highlight: $selectedView)
41
41
. measureSize { size in
42
42
tableSize = size
43
43
}
@@ -91,18 +91,16 @@ struct InspectLayout: ViewModifier {
91
91
}
92
92
}
93
93
94
- enum DidCallInspectLayout : EnvironmentKey {
95
- static var defaultValue : Bool = false
94
+ @available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
95
+ enum LogStoreKey : EnvironmentKey {
96
+ static var defaultValue : LogStore ? = nil
96
97
}
97
98
99
+ @available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
98
100
extension EnvironmentValues {
99
- /// Marker to signal that a valid LogStore environment object has been injected.
100
- /// Clients that use `@EnvironmentObject var logStore: LogStore` must verify that
101
- /// this value is true before accessing the environment object because it may be
102
- /// missing.
103
- var didCallInspectLayout : Bool {
104
- get { self [ DidCallInspectLayout . self] }
105
- set { self [ DidCallInspectLayout . self] = newValue }
101
+ var logStore : LogStore ? {
102
+ get { self [ LogStoreKey . self] }
103
+ set { self [ LogStoreKey . self] = newValue }
106
104
}
107
105
}
108
106
@@ -111,16 +109,11 @@ struct DebugLayoutModifier: ViewModifier {
111
109
var label : String
112
110
var file : StaticString
113
111
var line : UInt
114
- @Environment ( \. didCallInspectLayout) private var didCallInspectLayout
115
- /// The log store for the current inspectLayout() subtree.
116
- ///
117
- /// - Important: You must verify that `didCallInspectLayout == true` before accessing
118
- /// this property. Failure to do so will result in a crash as the object won't be
119
- /// in the environment.
120
- @EnvironmentObject private var logStore : LogStore
112
+ // Using @Environment rather than @EnvironmentObject because we don't want to observe this.
113
+ @Environment ( \. logStore) var logStore : LogStore ?
121
114
122
115
func body( content: Content ) -> some View {
123
- if didCallInspectLayout {
116
+ if let logStore {
124
117
DebugLayout ( label: label, logStore: logStore) {
125
118
content
126
119
}
@@ -196,9 +189,14 @@ struct ClearDebugLayoutLog: Layout {
196
189
197
190
@available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
198
191
public final class LogStore : ObservableObject {
199
- @Published public var log : [ LogEntry ] = [ ]
192
+ @Published public var log : [ LogEntry ]
200
193
var viewLabels : Set < String > = [ ]
201
194
195
+ init ( log: [ LogEntry ] = [ ] ) {
196
+ self . log = log
197
+ self . viewLabels = Set ( log. map ( \. label) )
198
+ }
199
+
202
200
func registerViewLabelAndWarnIfNotUnique( _ label: String , file: StaticString , line: UInt ) {
203
201
DispatchQueue . main. async { [ self ] in
204
202
if viewLabels. contains ( label) {
0 commit comments