You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 21:10:26