SwiftUI中NavigationLink目标视图不更新的问题及原因咨询
核心问题:SwiftUI依赖追踪的两种不同表现
1. 内联写法失效的本质
你把目标视图直接写在NavigationLink的destination闭包里时,这段代码只会在第一次创建这个NavigationLink的时候执行一次。虽然你用到了database.isOpen,但:
Database是普通类,不是ObservableObject,它的属性变化无法主动通知SwiftUI- 内闭包没和
database.isOpen建立持续的订阅关系,后续isOpen变化时,闭包不会重新执行,目标视图会停留在初始渲染状态
2. 独立视图能生效的原因
换成带@Binding var database: Database的独立Destination视图后:
@Binding会把这个视图的渲染与database实例绑定在一起- 只要有触发视图更新的操作(比如滑动关闭数据库),SwiftUI重新计算视图树时,
Destination的body会重新读取database.isOpen的最新值 - 而且
@Binding能追踪到database内部属性的变化,哪怕Database不是ObservableObject,只要password修改导致isOpen变化,Destination就会自动重新渲染,同步显示最新状态
为什么列表图标能正常更新?
你的DatabaseItem视图同样使用了@Binding var database,滑动关闭数据库后,SwiftUI会因为滑动操作触发局部视图更新,DatabaseItem的body会重新读取isOpen的新值,所以图标能正确切换。但内联的目标视图没有这种自动重新计算的机制,封装成独立视图后才通过@Binding补上了依赖关系。
额外优化建议
如果想让Database的属性变化能主动通知SwiftUI,更规范的做法是让它遵循ObservableObject协议,把password标记为@Published:
class Database: ObservableObject { var name: String @Published var password: String? var isOpen: Bool { password != nil } init(_ name: String, password: String? = nil) { self.name = name self.password = password } }
这样无论视图是否封装,SwiftUI都能精准感知password的变化,自动更新所有依赖该属性的视图。
内容的提问来源于stack exchange,提问作者astroboy
相关产品推荐
相关产品推荐

