@@ -3,11 +3,17 @@ import Foundation
3
3
@propertyWrapper
4
4
public struct State < Value> : DynamicProperty , StateProperty {
5
5
class Storage {
6
- var value : Value
6
+ // This inner box is what stays constant between view updates. The
7
+ // outer box (Storage) is used so that we can assign this box to
8
+ // future state instances from the non-mutating
9
+ // `update(with:previousValue:)` method. It's vital that the inner
10
+ // box remains the same so that bindings can be stored across view
11
+ // updates.
12
+ var box : Box < Value >
7
13
var didChange = Publisher ( )
8
14
9
15
init ( _ value: Value ) {
10
- self . value = value
16
+ self . box = Box ( value: value )
11
17
}
12
18
}
13
19
@@ -19,21 +25,24 @@ public struct State<Value>: DynamicProperty, StateProperty {
19
25
20
26
public var wrappedValue : Value {
21
27
get {
22
- storage. value
28
+ storage. box . value
23
29
}
24
30
nonmutating set {
25
- storage. value = newValue
31
+ storage. box . value = newValue
26
32
didChange. send ( )
27
33
}
28
34
}
29
35
30
36
public var projectedValue : Binding < Value > {
31
- Binding (
37
+ // Specifically link the binding to the inner box instead of the outer
38
+ // storage which changes with each view update.
39
+ let box = storage. box
40
+ return Binding (
32
41
get: {
33
- storage . value
42
+ box . value
34
43
} ,
35
44
set: { newValue in
36
- storage . value = newValue
45
+ box . value = newValue
37
46
didChange. send ( )
38
47
}
39
48
)
@@ -49,8 +58,8 @@ public struct State<Value>: DynamicProperty, StateProperty {
49
58
50
59
public func update( with environment: EnvironmentValues , previousValue: State < Value > ? ) {
51
60
if let previousValue {
52
- storage. value = previousValue. storage. value
53
- storage. didChange = previousValue. didChange
61
+ storage. box = previousValue. storage. box
62
+ storage. didChange = previousValue. storage . didChange
54
63
}
55
64
}
56
65
@@ -62,11 +71,11 @@ public struct State<Value>: DynamicProperty, StateProperty {
62
71
return
63
72
}
64
73
65
- storage. value = state as! Value
74
+ storage. box . value = state as! Value
66
75
}
67
76
68
77
func snapshot( ) throws -> Data ? {
69
- if let value = storage. value as? Codable {
78
+ if let value = storage. box as? Codable {
70
79
return try JSONEncoder ( ) . encode ( value)
71
80
} else {
72
81
return nil
0 commit comments