Avatar
こういうコードだと,あらかじめカウントアップした状態で,最初の toggle 連打時には deinit 0 が 1 回,それ以降の連打時には deinit 0 が 2 回ずつ出力されるので,@State の挙動としては condition が変わって Counter が変わると @State のための変数が新しく作られるけれど,前に使っていた変数がまだ破棄されず生きていたらそれを使い回すが新しく作った方も画面表示に使わないだけで裏では保持し続ける,みたいな挙動になっていそうですね. @State に参照型を持たせるか値型を持たせるかで挙動が変わりそうな気もするので Swift 5.9 ツールチェーンで @_moveOnly struct を作って使おうとしてみたんですが,State<T> みたいなジェネリクスでは noncopyable struct は使えないみたいで弾かれてしまいました... final class Count { let count: Int init(_ count: Int) { self.count = count } deinit { print("deinit \(count)") } } struct Counter: View { let name: String @State var count = Count(0) var body: some View { Button("\(name)=\(count.count)") { count = Count(count.count + 1) } } } struct ContentView: View { @State var condition = false var body: some View { if condition { VStack { Counter(name: "T") Button("toggle") { condition.toggle() } } } else { VStack { Counter(name: "F") Button("toggle") { condition.toggle() } } } } } (edited)
5:15 AM
ちなみに @StateObject@State だと挙動が違うので,上の例ではあくまでも @State の挙動を知るために @State に参照型を持たせてます.