Skip to content

Commit c88f90d

Browse files
committed
move shouldNotifyObservers logic into ObservationState
1 parent 4515383 commit c88f90d

File tree

4 files changed

+43
-44
lines changed

4 files changed

+43
-44
lines changed

Sources/ComposableArchitecture/Observation/ObservationStateRegistrar.swift

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,17 @@ extension ObservationStateRegistrar: Equatable, Hashable, Codable {
5151
keyPath: KeyPath<Subject, Member>,
5252
_ value: inout Value,
5353
_ newValue: Value,
54-
_ isIdentityEqual: (Value, Value) -> Bool
54+
_ isIdentityEqual: (Value, Value) -> Bool,
55+
_ shouldNotifyObservers: (Value, Value) -> Bool
5556
) {
5657
if isIdentityEqual(value, newValue) {
5758
value = newValue
5859
} else {
59-
self.registrar.withMutation(of: subject, keyPath: keyPath) {
60+
if shouldNotifyObservers(value, newValue) {
61+
self.registrar.withMutation(of: subject, keyPath: keyPath) {
62+
value = newValue
63+
}
64+
} else {
6065
value = newValue
6166
}
6267
}
@@ -101,12 +106,13 @@ extension ObservationStateRegistrar: Equatable, Hashable, Codable {
101106
keyPath: KeyPath<Subject, Member>,
102107
_ member: inout Member,
103108
_ oldValue: Member,
104-
_ isIdentityEqual: (Member, Member) -> Bool
109+
_ isIdentityEqual: (Member, Member) -> Bool,
110+
_ shouldNotifyObservers: (Member, Member) -> Bool
105111
) {
106112
if !isIdentityEqual(oldValue, member) {
107113
let newValue = member
108114
member = oldValue
109-
self.mutate(subject, keyPath: keyPath, &member, newValue, isIdentityEqual)
115+
self.mutate(subject, keyPath: keyPath, &member, newValue, isIdentityEqual, shouldNotifyObservers)
110116
}
111117
}
112118
}

Sources/ComposableArchitectureMacros/ObservableStateMacro.swift

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -647,20 +647,16 @@ public struct ObservationStateTrackedMacro: AccessorMacro {
647647
let setAccessor: AccessorDeclSyntax =
648648
"""
649649
set {
650-
guard shouldNotifyObservers(_\(identifier), newValue) else {
651-
return
652-
}
653-
\(raw: ObservableStateMacro.registrarVariableName).mutate(self, keyPath: \\.\(identifier), &_\(identifier), newValue, _$isIdentityEqual)
650+
\(raw: ObservableStateMacro.registrarVariableName).mutate(self, keyPath: \\.\(identifier), &_\(identifier), newValue, _$isIdentityEqual, shouldNotifyObservers)
654651
}
655652
"""
656653
let modifyAccessor: AccessorDeclSyntax = """
657654
_modify {
658655
let oldValue = _$observationRegistrar.willModify(self, keyPath: \\.\(identifier), &_\(identifier))
659-
yield &_\(identifier)
660-
guard shouldNotifyObservers(oldValue, \(identifier)) else {
661-
return
656+
defer {
657+
_$observationRegistrar.didModify(self, keyPath: \\.\(identifier), &_\(identifier), oldValue, _$isIdentityEqual, shouldNotifyObservers)
662658
}
663-
_$observationRegistrar.didModify(self, keyPath: \\.\(identifier), &_\(identifier), oldValue, _$isIdentityEqual)
659+
yield &_\(identifier)
664660
}
665661
"""
666662

Tests/ComposableArchitectureMacrosTests/ObservableStateMacroTests.swift

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,14 @@
3737
return _count
3838
}
3939
set {
40-
guard shouldNotifyObservers(_count, newValue) else {
41-
return
42-
}
43-
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual)
40+
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual, shouldNotifyObservers)
4441
}
4542
_modify {
4643
let oldValue = _$observationRegistrar.willModify(self, keyPath: \.count, &_count)
47-
yield &_count
48-
guard shouldNotifyObservers(oldValue, count) else {
49-
return
44+
defer {
45+
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual, shouldNotifyObservers)
5046
}
51-
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual)
47+
yield &_count
5248
}
5349
}
5450
@@ -103,18 +99,14 @@
10399
return _count
104100
}
105101
set {
106-
guard shouldNotifyObservers(_count, newValue) else {
107-
return
108-
}
109-
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual)
102+
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual, shouldNotifyObservers)
110103
}
111104
_modify {
112105
let oldValue = _$observationRegistrar.willModify(self, keyPath: \.count, &_count)
113-
yield &_count
114-
guard shouldNotifyObservers(oldValue, count) else {
115-
return
106+
defer {
107+
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual, shouldNotifyObservers)
116108
}
117-
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual)
109+
yield &_count
118110
}
119111
}
120112
@@ -169,18 +161,14 @@
169161
return _count
170162
}
171163
set {
172-
guard shouldNotifyObservers(_count, newValue) else {
173-
return
174-
}
175-
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual)
164+
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual, shouldNotifyObservers)
176165
}
177166
_modify {
178167
let oldValue = _$observationRegistrar.willModify(self, keyPath: \.count, &_count)
179-
yield &_count
180-
guard shouldNotifyObservers(oldValue, count) else {
181-
return
168+
defer {
169+
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual, shouldNotifyObservers)
182170
}
183-
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual)
171+
yield &_count
184172
}
185173
}
186174
@@ -232,18 +220,14 @@
232220
return _count
233221
}
234222
set {
235-
guard shouldNotifyObservers(_count, newValue) else {
236-
return
237-
}
238-
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual)
223+
_$observationRegistrar.mutate(self, keyPath: \.count, &_count, newValue, _$isIdentityEqual, shouldNotifyObservers)
239224
}
240225
_modify {
241226
let oldValue = _$observationRegistrar.willModify(self, keyPath: \.count, &_count)
242-
yield &_count
243-
guard shouldNotifyObservers(oldValue, count) else {
244-
return
227+
defer {
228+
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual, shouldNotifyObservers)
245229
}
246-
_$observationRegistrar.didModify(self, keyPath: \.count, &_count, oldValue, _$isIdentityEqual)
230+
yield &_count
247231
}
248232
}
249233

Tests/ComposableArchitectureTests/ObservableTests.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@ final class ObservableTests: BaseTCATestCase {
1818
XCTAssertEqual(state.count, 1)
1919
}
2020

21+
func testAssignEqualValue() async {
22+
var state = ChildState()
23+
24+
withPerceptionTracking {
25+
_ = state.count
26+
} onChange: {
27+
XCTFail("state.count should not change.")
28+
}
29+
30+
state.count = state.count
31+
XCTAssertEqual(state.count, 0)
32+
}
33+
2134
func testCopyMutation() async {
2235
XCTTODO(
2336
"""

0 commit comments

Comments
 (0)