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

SwiftUI NavigationView双栏动态列表右栏数据不实时刷新问题

问题原因

右栏无法实时刷新的核心问题是状态声明使用错误:
DataProvider是引用类型的ObservableObject,@Binding只能感知绑定值本身的替换(比如切换选中其他左栏条目时,选中实例被替换,右栏会刷新),但无法订阅实例内部@Published属性的变化。修改选中条目内部的子列表时,实例引用地址没有变化,@Binding不会触发右栏视图更新。

修改方案

只需要做两处最小改动即可实现实时刷新,不需要重构现有数据源逻辑:

  1. 将RightPane中的@Binding var dataProvider: DataProvider?替换为@ObservedObject var dataProvider: DataProvider?。@ObservedObject会自动订阅ObservableObject实例的所有@Published属性变化,内部数据更新时会主动触发视图重绘。
  2. 调整LeftPane中调用RightPane的传参方式,去掉$符号,直接传入选中的实例而非Binding引用,因为右栏不需要修改选中状态,只需要读取并观察选中实例的内容。
修改后完整可运行代码
//
//  DemoApp.swift
//  Shared
//
//  Created by Fred Appelman on 08/06/2022.
//

import SwiftUI

@main
struct DemoApp: App {
    var body: some Scene {
        WindowGroup {
            LeftPane()
        }
    }
}

class DataProvider: ObservableObject, Identifiable, Hashable {
    static func == (lhs: DataProvider, rhs: DataProvider) -> Bool {
        lhs.id == rhs.id
    }
    func hash(into hasher: inout Hasher) { hasher.combine(id) }
    
    let id = UUID()
    @Published var name: String
    @Published var data: [DataProvider]
    
    init(name: String, data: [DataProvider]) {
        self.name = name
        self.data = data
    }
}

struct RightPane: View {
    @ObservedObject var dataProvider: DataProvider?
    
    var body: some View {
        if let dataProvider = dataProvider {
            List(dataProvider.data, id: \.self) { item in
                Text(item.name)
            }
        } else {
            Text("Select in left pane")
        }
    }
}

struct LeftPane: View {
    @State var data: [DataProvider] = [
        DataProvider(name: "left-a", data: [
            DataProvider(name: "right-a1", data: []),
            DataProvider(name: "right-a2", data: [])
        ]),
        DataProvider(name: "left-b", data: [
            DataProvider(name: "right-b1", data: []),
            DataProvider(name: "right-b2", data: [])
        ]),
    ]
    @State private var selectedProvider: DataProvider?
    
    var body: some View {
        NavigationView {
            List(data, id: \.self, selection: $selectedProvider) { element in
                Text(element.name)
            }
            RightPane(dataProvider: selectedProvider)
        }
        Button("Add extra data")
        {
            let extraDataLeftPane = DataProvider(name: "left-c", data: [
                DataProvider(name: "right-c1",data: []),
                DataProvider(name: "right-c2",data: [])
            ])
            data.append(extraDataLeftPane)

            data[0].data.append(DataProvider(name: "right-a3", data: []))
        }
    }
}

修改后选中左栏首个条目点击添加按钮,右栏会立即显示新增的right-a3条目,不需要切换选中项。


内容的提问来源于stack exchange,提问作者Fred Appelman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.02 21:03:40