よくある誤用パターン
SwiftUIでObservableObjectを使用する際、その本来の目的を誤解しているケースが見られます。
具体的な問題例
@Publishedプロパティを定義し変更を検知するようにしているが、その値は条件分岐のみに使用されていて単なるロジックの切り替えのみの場合は不要です。
誤解の原因
おそらく「SwiftUIで変数を使う場合はObservableObjectが必要」と理解しているのではないでしょうか。
SwiftUIにおける変数の挙動
class MyObject {
var value: Int = 0
}
struct ContentView: View {
let object = MyObject()
var body: some View {
Button("Update") {
object.value = 100 // 値は更新される
}
}
}
このコードでは:
-
object.valueの値は確かに更新される - しかし、SwiftUIに変更が通知されないため画面は更新されない
- 別の理由でビューが更新された時に、新しい値が使われる
このことから分かる通り、変数の更新自体は行われています。ただし、それがSwiftUIに通知されず画面に表れないため、勘違いが生じていると考えられます。
また、別の例を使ってみましょう。
struct ConditionalBranchView: View {
var notObserve: ConditionalBranchNotObserve = .init()
var body: some View {
VStack(spacing: 50) {
Text("notObserve.bool: \(notObserve.bool)")
Button(action: {
if notObserve.bool {
print("pop")
}
}, label: {
Text("ConditionalBranch")
})
Button(action: {
notObserve.bool.toggle()
}, label: {
Text("change bool")
})
}
}
}
class ConditionalBranchNotObserve {
var bool: Bool = true
}
動画の通り画面の更新はされていませんが、条件分岐は正しく作用しています。
値の変更通知について
ObservableObject、@Published、@Stateは全て値の更新を検知し、その変更をSwiftUIに通知して画面更新をトリガーする仕組みです。
仕組みの違い
-
@State: SwiftUIが値を管理し、変更時に自動的にビューを再描画 -
@Published: プロパティの変更をObservableObjectのobjectWillChange通知としてビューに伝える - 通常の変数: 値は変わるが、SwiftUIへの通知は行われない
結論
- SwiftUIであろうと何であろうと、変数は特別な宣言なしに値が切り替わる
-
ObservableObjectや@Published、@Stateはあくまで値の変更をSwiftUIに通知し、画面更新をトリガーするための仕組み - 画面に影響しないロジックの制御のみに使う変数には不要
- 単なる条件分岐やロジック制御だけなら、通常のプロパティで十分
gitに今回作成したプロジェクトファイルをあげています。
https://github.com/Twada9/ObservableTestForArticle
