|
90 | 90 | private let store: Store<IdentifiedArray<ID, State>, IdentifiedAction<ID, Action>>
|
91 | 91 | private let data: IdentifiedArray<ID, State>
|
92 | 92 |
|
| 93 | + #if swift(<5.10) |
| 94 | + @MainActor(unsafe) |
| 95 | + #else |
| 96 | + @preconcurrency@MainActor |
| 97 | + #endif |
93 | 98 | fileprivate init(_ store: Store<IdentifiedArray<ID, State>, IdentifiedAction<ID, Action>>) {
|
94 | 99 | self.store = store
|
95 | 100 | self.data = store.withState { $0 }
|
|
98 | 103 | public var startIndex: Int { self.data.startIndex }
|
99 | 104 | public var endIndex: Int { self.data.endIndex }
|
100 | 105 | public subscript(position: Int) -> Store<State, Action> {
|
101 |
| - guard self.data.indices.contains(position) |
102 |
| - else { |
103 |
| - return Store() |
104 |
| - } |
105 |
| - let id = self.data.ids[position] |
106 |
| - var element = self.data[position] |
107 |
| - return self.store.scope( |
108 |
| - id: self.store.id(state: \.[id:id]!, action: \.[id:id]), |
109 |
| - state: ToState { |
110 |
| - element = $0[id: id] ?? element |
111 |
| - return element |
112 |
| - }, |
113 |
| - action: { .element(id: id, action: $0) }, |
114 |
| - isInvalid: { !$0.ids.contains(id) } |
| 106 | + precondition( |
| 107 | + Thread.isMainThread, |
| 108 | + #""" |
| 109 | + Store collections must be interacted with on the main actor. |
| 110 | +
|
| 111 | + When passing a scoped store to a 'ForEach' in a lazy view (for example, 'LazyVStack'), it \ |
| 112 | + must be eagerly transformed into a collection to avoid access off the main actor: |
| 113 | +
|
| 114 | + Array(store.scope(state: \.elements, action: \.elements)) |
| 115 | + """# |
115 | 116 | )
|
| 117 | + return MainActor._assumeIsolated { [uncheckedSelf = UncheckedSendable(self)] in |
| 118 | + let `self` = uncheckedSelf.wrappedValue |
| 119 | + guard self.data.indices.contains(position) |
| 120 | + else { |
| 121 | + return Store() |
| 122 | + } |
| 123 | + let id = self.data.ids[position] |
| 124 | + var element = self.data[position] |
| 125 | + return self.store.scope( |
| 126 | + id: self.store.id(state: \.[id:id]!, action: \.[id:id]), |
| 127 | + state: ToState { |
| 128 | + element = $0[id: id] ?? element |
| 129 | + return element |
| 130 | + }, |
| 131 | + action: { .element(id: id, action: $0) }, |
| 132 | + isInvalid: { !$0.ids.contains(id) } |
| 133 | + ) |
| 134 | + } |
116 | 135 | }
|
117 | 136 | }
|
118 | 137 | #endif
|
0 commit comments