こういうコードだと,あらかじめカウントアップした状態で,最初の 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)