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

SwiftUI点击MainView按钮触发ListRowView子视图updatePoints方法实现问询

解决方案

你的触发思路是可行的,现有代码主要存在数据流向错误、状态监听缺失、属性包装器使用错误三类问题,修正方案如下:


核心改动点

  • 修正数据绑定:Player实例需要用@Binding包装,确保子视图修改积分后能同步到父视图的Game模型
  • 状态职责拆分:每行独立的加减状态下沉到ListRowView内部,不要放在父视图全局共享
  • 补充状态监听:使用SwiftUI内置的onChange修饰符监听触发标记的变化,自动执行积分更新逻辑
  • 移除子视图对全局触发标记的修改,避免多实例同时修改状态混乱

修正后完整代码

MainView.swift

struct MainView: View {
    
    @Binding var game : Game
    @State private var invokeFunction : Bool = false
    
    var body: some View {
        NavigationView {
            List {
                Section {
                    // 遍历绑定数组,给子视图传递可修改的Player绑定
                    ForEach($game.players, id: \.self) { $player in
                        ListRowView(invokeFunction: $invokeFunction, player: $player)
                    }
                }
                Button(action: {
                    invokeFunction.toggle()
                }) {
                    Text("Calculate")
                }
            }
        }
    }
}

ListRowView.swift

struct ListRowView: View {
    
    @Binding var invokeFunction : Bool 
    @Binding var player : Player
    // 每行独立的加减状态
    @State private var addingPoints : Bool = true
    // 补充原来缺失的输入框文本状态
    @State private var inputText = ""
    
    var body: some View {
        HStack {
            Text(player.name)
            Spacer()
            Text("\(player.points)")
            Spacer()
            
            Button(action: {
                addingPoints.toggle()
            }) {
                if addingPoints {
                    Image(systemName: "plus.circle.fill")
                        .foregroundColor(.green)
                } else {
                    Image(systemName: "minus.circle.fill")
                        .foregroundColor(.red)
                }
            }.buttonStyle(BorderlessButtonStyle())
            
            TextField("0", text: $inputText)
                .keyboardType(.numberPad)
        }
        // 监听触发标记变化,执行积分更新逻辑
        .onChange(of: invokeFunction) { _ in
            updatePoints()
        }
    }
    
    private func updatePoints() {
        let newPoints = Int(inputText) ?? 0
        guard newPoints != 0 else { return }
        
        if addingPoints {
            player.points += newPoints
            print("加积分 \t 旧积分: \(player.points - newPoints) - 新积分: \(player.points)")
        } else {
            player.points -= newPoints
            print("减积分 \t 旧积分: \(player.points + newPoints) - 新积分: \(player.points)")
        }
        // 可选操作:执行完成后清空输入框
        inputText = ""
    }
}

原有Player结构体无需修改。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:15:03