如何创建可在不同结构体中读写的变量?SwiftUI @State跨视图访问问题
SwiftUI 跨视图共享可读写状态方案
你当前遇到的核心问题是@State的设计限制:@State是专门用于单个视图内部的私有状态,即使加了public修饰也无法实现跨视图的状态同步,子视图拿到的只是值拷贝,既无法反向修改父视图的原值,也无法自动获取最新的状态变更。
根据你的视图层级关系,有两种成熟的实现方案:
方案1:父子视图层级用@Binding传递
如果两个需要读写lane的视图是直接/间接的父子关系,用@Binding做状态绑定是最轻量的选择:
- 父视图中保留
@State定义的源状态:
@State private var lane = 2 // 替换为你需要的初始值
- 给操作
lane的按钮视图(也就是你给出的HStack所在的视图)声明@Binding类型的lane属性,替代原来的@State定义:
struct LaneControlView: View { @Binding var lane: Int var body: some View { // 你原来的HStack代码直接放这里即可,对lane的加减操作会自动同步到父视图 HStack { Button(action : { if (lane != 1) { lane -= 1 } }) { Rectangle() .frame(width: 200, height: 900) .opacity(0) } Button(action: { if (lane != 4) { lane += 1 } }) { Rectangle() .frame(width: 200, height: 900) .opacity(0) } } } }
- 父视图调用子视图时,传递绑定值(前缀加
$):
LaneControlView(lane: $lane)
- 另一个需要访问
lane最新值的视图,同样声明@Binding var lane: Int,父视图调用时也传递$lane即可,你需要的判断逻辑里直接访问lane就是最新值:
struct EnemyCheckView: View { @Binding var lane: Int // 其他属性定义 var body: some View { // 其他逻辑 if(carLane == enemyLane && Enemy1OffsetY == 150) { fatalError() } } }
方案2:跨多层级/多视图共享用ObservableObject
如果两个视图层级距离远,或者整个项目多个地方都要用到lane状态,用ObservableObject做全局共享状态更合适:
- 先定义继承自
ObservableObject的状态管理类:
class GameState: ObservableObject { @Published var lane = 2 // @Published修饰会自动通知所有订阅视图状态变更 }
- 在项目的根视图层级注入状态实例:
@main struct YourGameApp: App { @StateObject private var gameState = GameState() var body: some Scene { WindowGroup { ContentView() .environmentObject(gameState) } } }
- 所有需要读写
lane的视图,都声明@EnvironmentObject属性获取状态实例:
// 按钮控制视图 struct LaneControlView: View { @EnvironmentObject var gameState: GameState var body: some View { HStack { Button(action : { if (gameState.lane != 1) { gameState.lane -= 1 } }) { Rectangle() .frame(width: 200, height: 900) .opacity(0) } // 另一个按钮同理,操作gameState.lane即可 } } }
// 碰撞检测视图 struct EnemyCheckView: View { @EnvironmentObject var gameState: GameState // 其他属性 var body: some View { // 直接访问gameState.lane就是最新值 if(carLane == enemyLane && Enemy1OffsetY == 150) { fatalError() } } }
注意事项
- 不要给
@State添加public修饰,完全不符合@State的设计定位,无法实现跨视图同步 - 使用
@EnvironmentObject时要确保注入层级足够高,所有用到该状态的子视图都在注入层级的下方,否则会触发运行时错误
内容的提问来源于stack exchange,提问作者Superbia
相关产品推荐
相关产品推荐

