Open1
SwiftUI: delegateから呼んだ@Stateが更新されない
View
に、何かのdelegateプロトコルを実装し、そのメソッドから@State
の変数を更新するんですが、これが全然表示に反映されない、という現象にハマリました。
以下のような奴です。
protocol SomeDelegate {
func didSomething()
}
struct SomeView: View, SomeDelegate {
var someManager: SomeManager
@State var someText: String = ""
init() {
self.someManager = SomeManager()
self.someManager.delegate = self
}
func didSomething() {
self.someText = "done!"
}
var body: some View {
Text(someText)
}
}
何かのきっかけでSomeManager
が.delegate.didSomthing()
を発火するんですが、実際にdidSomething()
が呼ばれても、self.someText
は空文字列のままで表示は更新されません。
分かってしまえばなんてことはないのですが、これはdelegateを実装しているのがstruct
であることが原因です。
init
で渡しているself
と、didSomething()
が呼ばれたときのself
が違うんです。
関数呼び出しで引数としてstruct
の変数を渡して、渡した先の関数でそのstruct
のメンバを操作しているようなイメージですね。渡した先で操作した内容は、呼び出し元には反映されません。
修正するとすれば、以下のような感じでしょうか。
-
ObservableObject
や@Observable
のclass
を使ってdelegateを新たに作る - そのクラスの
didSomething()
でメンバ変数を更新する - (
ObservableObject
の場合)更新するメンバ変数は@Published
にする -
View
にメンバとしてそのdelegateクラスのオブジェクトを持たせる(ObservableObject
の場合、@ObservedObject
にする) -
View
はdelegateクラスのメンバ変数を見て表示を更新する