Sponsor Link
環境&対象
- macOS Big Sur 11.2.1
- Xcode 12.4
@Published
@Published が付与されたプロパティは、更新されるとビューが更新されます。
この説明がよくみる @Published の説明だと思います。
@Published は、Combine フレームワークの一部
Apple のドキュメントを読んで最初に気づくのは、@Published は、SwiftUI ではなく Combine の一部として提供されていることです。
Apple のドキュメントは、こちら。
@Published は、Publisher を作る
@Published が役に立つのはビューを更新させたい時だけではありません。
@Published を指定すると、$ (つまり、projectedValue) として、そのプロパティの Publisher にアクセスすることができます。
(property wrapper として、Publisher を作成してくれるということです)
ドキュメントのサンプルにもありますが、以下のように、使うことができます。
class Weather {
@Published var temperature: Double
init(temperature: Double) {
self.temperature = temperature
}
}
let weather = Weather(temperature: 20)
cancellable = weather.$temperature
.sink() {
print ("Temperature now: \($0)")
}
weather.temperature = 25
// Prints:
// Temperature now: 20.0
// Temperature now: 25.0
変数監視
従来の変数監視
Swiftが当初から持っている変数の監視は、以下のようなものです。
import Foundation
class Test {
var test2:Int = 10 {
willSet{
print("willSet (\(test2) -> \(newValue))")
}
didSet{
print("didSet (\(oldValue) -> \(test2))")
}
}
}
func update(test:Test) {
test.test2 += 1
}
let test = Test()
test.test2 = 11 // 10 -> 11
update(test:test) // 11 -> 12
// Prints:
//willSet (10 -> 11)
//didSet (10 -> 11)
//willSet (11 -> 12)
//didSet (11 -> 12)
Combine 的変数監視 が @Published
変数監視を Combine的に実装すると この @Published になるということだと思います。
@Published というプロパティラッパーを設定しておくことで、$ 経由でその Publisher に簡単にアクセスでき、sink や assign をすることで、変数監視の実装が可能となります。
複数から監視することも可能なので、さらに便利です。
SwiftUI でのビュー更新
SwiftUI でのビューの更新は、@Published と ObservableObject/@ObservedObject の組み合わせにより実現されています。
ビューの更新は、この Publisher を subscribe することによって実装されています(ハズ)。
Apple のドキュメントは、こちら。
ObservableObject に準拠させたクラスは objectWillChange というプロパティ(Publisher)を持ちます。
@Published 指定されたプロパティに変化が起こる直前に objectWillChange に通知され、objectWillChange が Publisher として変化を通知して・・・・
これが、SwiftUI でのビュー更新の背景で起こっていること(のハズ)です。
ちなみに、@Published, ObservableObject, @ObservedObject のうち、@ObservedObject のみが SwiftUI 提供の struct です。
@Published だけでなく、ObservableObject も Combine の提供するものでした。このあたりも興味深いです。
なんとなく、ObservableObject と @ObservedObject がペアな気がしていたのですが、一方は Combine から 他方は SwiftUI から提供されていました。
まとめ:@Published は、変数監視の Combine 実装
- willSet/didSet の Combine 版が @Published
- SwiftUI でのビューの更新は、@Published/ObservableObject/@ObservedObject の組み合わせで実現されている
上で、willSet/didSet の Combine 版と書いていますが、厳密には、@Published は willSet の タイミングで Publish されることに注意しないといけません。
“更新される/た” ことにのみ着目しているのであれば問題ないかもしれませんが、”更新された値” に着目しているのであれば、@Published は、willSet のタイミングで Publish されていることに気をつけないといけません。
@Published が willSet で Publish されるのは、SwiftUI が View の更新するときに、前後の値が 必要になるためだと思います。(SwiftUI は、指定されればアニメーションを行うことが要求されます)
“更新された値”に着目しているのであれば、@Published ではなく自前の objectDidChange 的な通知を使用する方が自然だと思います。
例えば、CurrentValueSubject は、didSet 相当で Publish されます。
すでにそのように理解している人は多いかもしれませんが、改めて考察してみました。
Swift 学習におすすめの本
詳解Swift
Swift の学習には、詳解 Swift という書籍が、おすすめです。
著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。
最新版を購入するのがおすすめです。
現時点では、上記の Swift 5 に対応した第5版が最新版です。
Swift ポケットリファレンス
Swift を学んでも、プログラミング言語の文法を全て記憶しておくことは無理なので、ちょっとした文法の確認をするために、リファレンス本を手元に置いておくと便利です。
Swift4 までしか対応していないので、相違点を理解して参照する必要があります。
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link