2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【SwiftUI】@Publishedを@Publishedを使わずに表してみる

Last updated at Posted at 2023-05-03

はじめに

タイトルが頭痛が痛いみたいになってしまいました。ごめんなさい。語彙力がないんです...😭
@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更新タイミングを細かく制御する

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?