@@ -3,11 +3,17 @@ import Foundation
33@propertyWrapper
44public struct State < Value> : DynamicProperty , StateProperty {
55 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 >
713 var didChange = Publisher ( )
814
915 init ( _ value: Value ) {
10- self . value = value
16+ self . box = Box ( value: value )
1117 }
1218 }
1319
@@ -19,21 +25,24 @@ public struct State<Value>: DynamicProperty, StateProperty {
1925
2026 public var wrappedValue : Value {
2127 get {
22- storage. value
28+ storage. box . value
2329 }
2430 nonmutating set {
25- storage. value = newValue
31+ storage. box . value = newValue
2632 didChange. send ( )
2733 }
2834 }
2935
3036 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 (
3241 get: {
33- storage . value
42+ box . value
3443 } ,
3544 set: { newValue in
36- storage . value = newValue
45+ box . value = newValue
3746 didChange. send ( )
3847 }
3948 )
@@ -49,8 +58,8 @@ public struct State<Value>: DynamicProperty, StateProperty {
4958
5059 public func update( with environment: EnvironmentValues , previousValue: State < Value > ? ) {
5160 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
5463 }
5564 }
5665
@@ -62,11 +71,11 @@ public struct State<Value>: DynamicProperty, StateProperty {
6271 return
6372 }
6473
65- storage. value = state as! Value
74+ storage. box . value = state as! Value
6675 }
6776
6877 func snapshot( ) throws -> Data ? {
69- if let value = storage. value as? Codable {
78+ if let value = storage. box as? Codable {
7079 return try JSONEncoder ( ) . encode ( value)
7180 } else {
7281 return nil
0 commit comments