SwiftUI视图值未更新求助:跨视图修改数据不生效
SwiftUI跨视图数据更新不同步问题解决
问题根源
- ViewModel实例不共享:MainScreenView跳转到FocusedBalanceView时新建了
PlayerDataViewModel()实例,两个视图操作的是独立数据源,修改后主视图的原始数据无变化。 - 值类型属性修改未触发更新:PlayerData是结构体(值类型),直接修改数组元素的
balance属性时,数组本身的引用未改变,@Published仅在数组整体替换时才会通知视图刷新。
修复步骤
1. 共享同一个ViewModel实例
修改MainScreenView的NavigationLink,传递当前的viewModel而非新建实例:
// MainScreenView中的NavigationLink修改为: NavigationLink(destination: FocusedBalanceView(SelectedPlayerIndex: 0, viewModel: viewModel)) { // 原有UI内容保持不变 }
2. 通过ViewModel方法触发数据更新
在PlayerDataViewModel中添加更新余额的方法,确保修改后数组引用发生变化,触发@Published通知:
class PlayerDataViewModel: ObservableObject { @Published var PlayerDataList: [PlayerData] = [ PlayerData(id: 0, name: "Player1", balance: 1500, iconname: "car.side.fill", active: true, accentColor: .red), PlayerData(id: 1, name: "Player2", balance: 1500, iconname: "ferry.fill", active: true, accentColor: .green), PlayerData(id: 2, name: "Player3", balance: 1500, iconname: "airplane", active: true, accentColor: .green), PlayerData(id: 3, name: "Player4", balance: 1500, iconname: "fan.ceiling.fill", active: true, accentColor: .white) ] // 添加更新余额的方法 func updateBalance(for playerId: Int, amount: Int) { guard let index = PlayerDataList.firstIndex(where: { $0.id == playerId }) else { return } var updatedPlayer = PlayerDataList[index] updatedPlayer.balance += amount PlayerDataList[index] = updatedPlayer } }
3. 修改FocusedBalanceView的按钮动作
使用ViewModel的方法更新余额,替代直接修改数组元素属性:
// FocusedBalanceView中的按钮动作修改为: Button(action: { viewModel.updateBalance(for: viewModel.PlayerDataList[SelectedPlayerIndex].id, amount: 500) }) { Image(systemName: "car") .frame(width: 70, height: 70) .foregroundColor(.white) .fontWeight(.bold) .font(.title) .background(.green) .clipShape(Circle()) } Button(action: { viewModel.updateBalance(for: viewModel.PlayerDataList[SelectedPlayerIndex].id, amount: -500) }) { Image(systemName: "dollarsign") .frame(width: 70, height: 70) .foregroundColor(.white) .fontWeight(.bold) .font(.title) .background(.red) .clipShape(Circle()) } Button(action: { viewModel.updateBalance(for: viewModel.PlayerDataList[SelectedPlayerIndex].id, amount: -250) }) { Image(systemName: "mappin.and.ellipse") .frame(width: 70, height: 70) .foregroundColor(.white) .fontWeight(.bold) .font(.title) .background(.blue) .clipShape(Circle()) }
4. 修复Picker标签类型不匹配问题
FocusedBalanceView中Picker的selection为Int类型,需将tag改为对应类型:
// FocusedBalanceView中的Picker修改为: Picker("Balance", selection: $SelectedPlayerIndex) { ForEach(viewModel.PlayerDataList) { item in if item.active == true { HStack { Text("\(item.name)").tag(item.id) // 改为Int类型的item.id Image(systemName: item.iconname) } } } }
完成以上修改后,主视图与子视图将共享同一数据源,数据修改会同步触发视图刷新,主视图即可显示最新余额数值。
内容的提问来源于stack exchange,提问作者NitroNite72
相关产品推荐
相关产品推荐

