为何在View.init()中设置代理无法更新SwiftUI的@State变量?
SwiftUI视图状态更新失效问题分析
问题代码
struct TestView: View { @State var text = "Hello" let useCase = TestUseCase() init() { useCase.output = self } var body: some View { Text(text) .onAppear { // ① useCase.output = self useCase.show() } } } extension TestView: TestUseCaseOutput { func showText(text: String) { self.text = text } } class TestUseCase { var output: TestUseCaseOutput? func show() { output?.showText(text: "Changed") } } protocol TestUseCaseOutput { func showText(text: String) }
问题现象
代码意图在视图显示时将text从"Hello"改为"Changed",但实际运行时:
showText方法已被调用,但text的变更未反映到界面上- 若将
useCase.output = self移到onAppear的①处,text能正常更新并同步到界面
原因解析
- SwiftUI的视图是值类型(struct),SwiftUI会在视图状态变化时重新计算
body,生成新的视图实例。 - 在
init中赋值的useCase.output = self,指向的是初始化阶段的旧视图实例;而onAppear执行时,界面上显示的是新的视图实例。当useCase回调showText时,修改的是旧实例的@State变量,自然无法触发当前界面的更新。 - 把
useCase.output = self放在onAppear中时,此时的self是当前显示在界面上的活跃视图实例,修改它的@State变量会触发SwiftUI的视图刷新逻辑,界面就能同步更新了。
内容的提问来源于stack exchange,提问作者Yamamoto
相关产品推荐
相关产品推荐

