When using as a State in view that contains a class object (as an example an Enum with associated values, or directly the class as a nillable state): When the body will trigger a state change, that should deallocate that object (as an example setting the enum to another value that do not contains the object as the associated value, or setting the state class to nil), the object is not deallocated If then the state change another time, setting the state to a third different value (ex: setting enum to a third case) the class object will be then deallocated. In case of not passing through a third state (ex. alternating nil and not nil object) the first object will be deallocated just before the new one is initiated.
This behaviour is not consistent with Swift memory retain system, State apparently is masking a retain inside its implementation, and no documentation appears to show this problem
I may suppose that the problem may due to the "onChange" modifier that will advertise a view of its old and new values, so state may retain the old class until the onChange is fired, but it should be smarter then the current behaviour
Any suggestions for a workaround? radar filed as FB13614543
You can reproduce using the following code
class MyClass {
init() {
print("Allocate")
}
deinit {
print("Deallocate")
}
}
enum LocalState {
case normal
case withClass(MyClass)
case third
}
struct ContentView: View {
@State
var localState: LocalState = .normal
@State
var oldState: LocalState?
var body: some View {
switch localState {
case .normal:
Button("Go To Class") {
self.localState = .withClass(MyClass())
}
case .withClass:
Button("Go To Third") {
self.localState = .third
}
case .third:
Button("Go To Normal") {
self.localState = .normal
}
}
}
}
@main
struct DemoApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}