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

SwiftUI如何向子视图传递可更新的只读数据

解决SwiftUI子视图只读展示ObservableObject数据的问题

你现在的代码用@Binding传递单个属性,确实存在子视图意外修改数据的风险。更稳妥的做法是直接传递整个User实例给ScoreView,利用@ObservedObject监听数据变化,同时保证子视图仅做只读展示。

具体改法:

  1. 调整ScoreView,接收完整的User对象
    用@ObservedObject修饰User实例,这样视图能自动响应@Published属性的变化,同时子视图只能通过对象读取属性,不会有直接修改父视图数据的绑定能力。

  2. 修改ContentView的调用方式
    直接把player和cpu实例传入ScoreView,不用加$创建绑定。

  3. 可选优化:让User的name不可修改
    如果name不需要后续变更,可以把它设为let,彻底避免被意外修改。

修改后的完整代码:

User类(可选优化name为let)

class User: ObservableObject {
    let name: String // 设为let,防止被修改
    @Published var score: Int
    
    init(name: String, score: Int) {
        self.name = name
        self.score = score
    }
}

ContentView

struct ContentView: View {
    
    @StateObject var player = User(name: "Player", score: 0)
    @StateObject var cpu = User(name: "CPU", score: 0)
    
    var body: some View {
        ZStack {
            Image("background-plain").resizable().ignoresSafeArea()
            VStack {
                Spacer()
                Image("logo")
                Spacer()
                HStack {
                    Spacer()
                    ScoreView(user: player) // 直接传实例
                    Spacer()
                    ScoreView(user: cpu)
                    Spacer()
                }
                .fontWeight(.semibold)
                .foregroundColor(.white)
                Spacer()
            }
        }
    }
}

ScoreView

struct ScoreView: View {
    
    @ObservedObject var user: User // 用@ObservedObject监听变化
    
    var body: some View {
        VStack {
            Text(user.name)
                .font(.headline)
                .padding(.bottom, 10)
            Text(String(user.score))
                .font(.largeTitle)
        }
    }
}

为什么这样更好?

  • @ObservedObject能让ScoreView自动响应User中@Published属性(比如score)的变化,完全满足你要同步更新的需求。
  • 子视图只能通过user.name和user.score读取数据,没有绑定的修改权限——就算想改,name是let的话直接编译报错,score要修改得写user.score = ...,但从视图职责来说,我们不会在纯展示的ScoreView里写这种代码,比用@Binding安全多了。
  • 传递完整对象的方式更符合面向对象设计,后续如果要给User加其他属性,也不用改ScoreView的参数,扩展性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 02:10:20