如何从NavigationView的详情视图内按钮更新其导航栏标题?
问题解决方法
这个问题的核心是父视图的numberOfRecords没有监听到详情页对记录状态的修改,只要让父子视图共享可响应状态变化的数据源即可,有三种常用实现方案:
方案1:使用@Binding传递状态(层级少于3级时首选)
父视图跳转时将对应记录的绑定传入详情页,详情页修改状态时会直接同步到父视图数据源:
- 父视图中修改
NavigationLink代码:
NavigationLink(destination: DetailView(record: $record))
- 详情页中声明
record为@Binding类型:
@Binding var record: Record
注意:父视图中的numberOfRecords需要设置为基于数据源的计算属性,才会在数据源变化时自动重新计算,示例代码如下:
var numberOfRecords: Int { records.filter { if showUnread { return !$0.isRead } if showFavorites { return $0.isFavorite } return true }.count }
方案2:使用ObservableObject全局托管数据源(多页面共享数据时首选)
将所有记录和过滤规则统一放在遵循ObservableObject协议的视图模型中,用@Published修饰可变属性:
class RecordViewModel: ObservableObject { @Published var records: [Record] = [] @Published var showUnread = false @Published var showFavorites = false // 自动计算当前展示的记录数 var numberOfRecords: Int { records.filter { if showUnread { return !$0.isRead } if showFavorites { return $0.isFavorite } return true }.count } }
父视图用@StateObject持有该视图模型,详情页用@EnvironmentObject接收该视图模型,任意页面修改数据源内容都会触发所有关联视图刷新,导航栏标题会自动更新。
方案3:使用闭包回调(自定义更新逻辑时使用)
在详情页定义状态修改完成的回调闭包,父视图跳转时传入回调触发自身数据源刷新:
- 详情页定义回调属性:
struct DetailView: View { var record: Record // 收藏状态修改后的回调 var onFavoriteUpdated: () -> Void // 收藏按钮点击逻辑 func toggleFavorite() { // 执行修改收藏状态的逻辑 onFavoriteUpdated() } }
- 父视图传入回调:
NavigationLink(destination: DetailView(record: record, onFavoriteUpdated: { // 执行父视图数据源刷新、重新计算记录数的逻辑 }))
内容的提问来源于stack exchange,提问作者JoostS
相关产品推荐
相关产品推荐

