SwiftUI外部类无法修改View的@State变量price问题求助
问题描述
点击「Show Next View」→「Change-Me」→「Return」后,ContentView中的@State变量price无法修改为9,相关代码如下:
class ExtenalClass { let SubFrutis = ContentView() func ExtChangePrice() { SubFrutis.fChangePrice() } } struct ContentView: View { @State var price: Int = 0 @State var vPresent = false func fChangePrice() { price = 9 print("Price Value is: \(String(price))") } var body: some View { VStack { Text(String(price)).padding() Button("Show Next View") { self.vPresent = true } .sheet(isPresented: $vPresent) { SecondView(vPresent: self.$vPresent) }.padding() Button("Add-Me") { price += 1 }.padding() Button("RESET") { price = 1 }.padding() } } } struct SecondView: View { @Binding var vPresent: Bool var vExtenal = ExtenalClass() var body: some View { Button("Change-Me") { vExtenal.ExtChangePrice() // ContentView().fChangePrice() }.padding() Button("Return") { self.vPresent = false } } }
问题根源
核心错误在于:ExtenalClass里创建的ContentView()是一个全新的实例,和屏幕上正在显示的ContentView完全无关。
@State是绑定到具体View实例的状态存储,修改新实例的price只会改变这个未渲染对象的值,不会影响界面上已存在的实例。- SwiftUI的View是值类型,每次调用
ContentView()都会生成独立的新对象,两者状态完全隔离。控制台能打印出Price Value is: 9,就是这个未显示的新实例的状态被修改了,但它从未被渲染到界面上,所以你看不到变化。
解决方案
方案1:直接通过@Binding传递状态(简单直观,适合小型场景)
不需要额外的ExtenalClass,直接把ContentView的price绑定传给SecondView,在SecondView里直接修改:
struct ContentView: View { @State var price: Int = 0 @State var vPresent = false var body: some View { VStack { Text(String(price)).padding() Button("Show Next View") { self.vPresent = true } .sheet(isPresented: $vPresent) { // 传递price的绑定给SecondView SecondView(vPresent: self.$vPresent, price: self.$price) }.padding() Button("Add-Me") { price += 1 }.padding() Button("RESET") { price = 1 }.padding() } } } struct SecondView: View { @Binding var vPresent: Bool // 接收price的绑定 @Binding var price: Int var body: some View { VStack { Button("Change-Me") { // 直接修改绑定的price price = 9 print("Price Value is: \(String(price))") }.padding() Button("Return") { self.vPresent = false } } } }
方案2:使用ObservableObject做全局状态管理(适合复杂场景)
如果后续需要在多个View或类中共享状态,推荐用ObservableObject统一管理状态,任何地方修改状态,关联的View都会自动更新:
// 定义状态管理类,遵守ObservableObject协议 class PriceManager: ObservableObject { // @Published标记的属性变化时,会通知所有订阅的View更新 @Published var price: Int = 0 func changePrice(to newValue: Int) { price = newValue print("Price Value is: \(String(price))") } } struct ContentView: View { // 用@StateObject创建状态管理器实例(iOS 14+) @StateObject private var priceManager = PriceManager() @State var vPresent = false var body: some View { VStack { // 绑定到priceManager的price Text(String(priceManager.price)).padding() Button("Show Next View") { self.vPresent = true } .sheet(isPresented: $vPresent) { // 传递状态管理器给SecondView SecondView(vPresent: self.$vPresent, priceManager: priceManager) }.padding() Button("Add-Me") { priceManager.price += 1 }.padding() Button("RESET") { priceManager.price = 1 }.padding() } } } struct SecondView: View { @Binding var vPresent: Bool // 用@ObservedObject接收状态管理器 @ObservedObject var priceManager: PriceManager var body: some View { VStack { Button("Change-Me") { // 通过状态管理器修改价格 priceManager.changePrice(to: 9) }.padding() Button("Return") { self.vPresent = false } } } }
内容的提问来源于stack exchange,提问作者Jacky Lau
相关产品推荐
相关产品推荐

