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

SwiftUI传递ViewModel至子视图时ForEach报错原因探究

问题原因分析

你遇到的三个错误本质上都是因为错误地对只读属性和计算值使用了Binding($符号),具体拆解:

  1. Cannot assign to property: 'keys' is a get-only property
    $viewModel.data 获取的是 Binding<[String: [String]]>,当你链式访问 .keys 时,Swift 会尝试创建一个指向字典 keys 属性的 Binding。但字典的 keys 是只读属性,Binding 要求绑定的属性必须是可读写的,因此触发这个错误。

  2. Cannot call value of non-function type... 和 Dynamic key path member lookup cannot refer to instance method 'sorted()'
    即便忽略只读问题,$viewModel.data.keys.sorted() 的写法逻辑也不成立:Binding 的动态成员查找只能访问属性,不能直接调用实例方法(比如 sorted())。这里的链式访问最终得到的是一个 Binding<() -> [String]> 类型的值,而 ForEach 需要的是一个普通的集合(比如 [String]),类型不匹配导致报错。

解决方法

你这里只是在 ContainerView 中展示数据,不需要对 data.keys 做双向绑定,直接去掉 $ 符号,访问 viewModel.data 的普通值即可。因为 @ObservedObject 会自动监听 viewModel 中 @Published 属性的变化,当 data 更新时,视图会自动刷新。

修正后的 ContainerView 代码:

struct ContainerView: View {
    @ObservedObject var viewModel: TestViewModel
    
    var body: some View {
        List() {
            // 去掉$符号,直接访问普通值
            ForEach(viewModel.data.keys.sorted(), id: \.self){ key in
                Text(key)
            }
        }
    }
}

如果之后需要在子视图中修改 viewModel.data 的内容(比如添加/删除键值对),也不需要对 keys 绑定,直接通过 viewModel.data 操作即可,因为 @ObservedObject 已经建立了监听关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:45:12