Skip to content

Commit 644201a

Browse files
committed
Use Signal pipe plus local variable instead of MutableProperty
for ViewStore state.
1 parent 06bb9ff commit 644201a

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

Sources/ComposableArchitecture/ViewStore.swift

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ public final class ViewStore<State, Action> {
6363
#endif
6464

6565
private let _send: (Action) -> Void
66-
fileprivate let _state: MutableProperty<State>
66+
private var _state: State
67+
fileprivate let _stateSubject = Signal<State, Never>.pipe()
6768
private var viewDisposable: Disposable?
6869

6970
/// Initializes a view store from a store.
@@ -76,7 +77,7 @@ public final class ViewStore<State, Action> {
7677
_ store: Store<State, Action>,
7778
removeDuplicates isDuplicate: @escaping (State, State) -> Bool
7879
) {
79-
self._state = MutableProperty(store.$state.value)
80+
self._state = store.$state.value
8081
self._send = store.send
8182

8283
self.viewDisposable = store.$state.producer
@@ -88,7 +89,8 @@ public final class ViewStore<State, Action> {
8889
self.objectWillChange.send()
8990
}
9091
#endif
91-
self._state.value = $0
92+
self._state = $0
93+
self._stateSubject.input.send(value: $0)
9294
}
9395
}
9496

@@ -99,12 +101,12 @@ public final class ViewStore<State, Action> {
99101

100102
/// The current state.
101103
public var state: State {
102-
self._state.value
104+
self._state
103105
}
104106

105107
/// Returns the resulting value of a given key path.
106108
public subscript<LocalState>(dynamicMember keyPath: KeyPath<State, LocalState>) -> LocalState {
107-
self._state.value[keyPath: keyPath]
109+
self._state[keyPath: keyPath]
108110
}
109111

110112
/// Sends an action to the store.
@@ -155,7 +157,7 @@ public final class ViewStore<State, Action> {
155157
send localStateToViewAction: @escaping (LocalState) -> Action
156158
) -> Binding<LocalState> {
157159
Binding(
158-
get: { get(self._state.value) },
160+
get: { get(self._state) },
159161
set: { newLocalState, transaction in
160162
if transaction.animation != nil {
161163
withTransaction(transaction) {
@@ -295,7 +297,10 @@ public struct StoreProducer<State>: SignalProducerConvertible {
295297

296298
fileprivate init<Action>(viewStore: ViewStore<State, Action>) {
297299
self.viewStore = viewStore
298-
self.upstream = viewStore._state.producer
300+
self.upstream = Property<State>(initial: viewStore.state, then: viewStore._stateSubject.output).producer
301+
// .on(completed: { [viewStore = self.viewStore] in
302+
// _ = viewStore
303+
// })
299304
}
300305

301306
private init(

Tests/ComposableArchitectureTests/ViewStoreTests.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,22 @@ final class ViewStoreTests: XCTestCase {
124124
XCTAssertEqual([0, 1, 2], results)
125125
}
126126
#endif
127+
128+
// func testPublisherOwnsViewStore() {
129+
// let reducer = Reducer<Int, Void, Void> { count, _, _ in
130+
// count += 1
131+
// return .none
132+
// }
133+
// let store = Store(initialState: 0, reducer: reducer, environment: ())
134+
//
135+
// var results: [Int] = []
136+
// ViewStore(store)
137+
// .produced.producer.logEvents(identifier: "test")
138+
// .startWithValues { results.append($0) }
139+
//
140+
// ViewStore(store).send(())
141+
// XCTAssertEqual(results, [0, 1])
142+
// }
127143
}
128144

129145
private struct State: Equatable {

0 commit comments

Comments
 (0)