はじめに
タイトルが頭痛が痛いみたいになってしまいました。ごめんなさい。語彙力がないんです...😭
@Published
がどんな挙動をしてるのかイマイチ分かっていなかったので、調べてみました。
結論
@Published var age: Int
は、
var age: Int {
willSet{
objectWillChange.send()
}
}
と表せる
@Published
よくある@Published
の使い方としては、例えば以下のようなPerson
クラスがあります。
ObservableObject
に準拠したクラスを定義して、状態の変更があった際にViewに変更を通知させたい(Viewを更新したい)プロパティに@Published
を付与します。
class Person: ObservableObject {
var name: String
@Published var age: Int
init(name: String, age: Int) {
self.name = name
self.age = age
}
func growOld() {
age += 1
}
}
View側では、作成したクラスのインスタンスに@ObservedObject
を付与することで、プロパティの変更を監視し、更新された時にビューに表示されている値も更新することができます。
struct ContentView: View {
@ObservedObject var bob = Person(name: "Bob", age: 20)
var body: some View {
VStack {
Text("名前:" + bob.name)
Text("年齢:" + String(bob.age))
Button {
bob.growOld()
} label: {
Text("歳を重ねる")
}
}
}
}
objectWillChange
class Person: ObservableObject {
var name: String
var age: Int {
willSet{
objectWillChange.send() // 変更を通知
}
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
func growOld() {
age += 1
}
}
objectWillChange
は、その名の通り観測可能オブジェクトが変更される前に呼び出され、変更が通知されるたびにサブスクライバ(観測可能な値の変更を通知するために使用されるオブジェクト)に値を送信するプロパティです。
...よく分かりませんよね。私もよく分かりません(泣)
要するに、Viewの更新を円滑に行うために、プロパティ(変数)の変更をViewに通知してくれるのがobjectWillChange
です(のはず)。
これを自動で行ってくれるのが、今まで使ってきた@Published
になります。
ちなみにobjectWillChange
を使う(@Published
で自動化しない)ことの利点として、変更を通知する条件を設定できるというものがあります。
class Person: ObservableObject {
var name: String
var age: Int {
willSet{
if age > 22 { // ageが22以下の時は変更を通知しない
objectWillChange.send()
}
}
}
init(name: String, age: Int) {
self.name = name
self.age = age
}
func growOld() {
age += 1
}
}
終わりに
使いこなせれば@Published
を使わない方が便利になるかもしれない...
参考:
(at)PublishedがどのようにSwiftUIのViewを更新するのか
ObservableObject利用時のView更新タイミングを細かく制御する