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

SwiftUI跨视图条件导航问题:校验TextField后跳转遇阻

问题分析与解决方案

核心问题

  1. 状态实例不共享:ButtonView内部新建了UserProgress实例,点击按钮时修改的是这个局部实例的状态,和mainViewApp中的实例完全独立,导致父视图无法感知按钮点击后的状态变化。
  2. 状态设计不合理:UserProgress的value字段被两个TextField同时覆盖,无法分别存储两个输入框的内容,校验逻辑无法准确获取两个输入值。
  3. 校验逻辑缺失:没有在按钮点击时触发对两个输入框的非空校验,也没有关联readyToNavigate的状态更新。

修改后的完整代码

class UserProgress: ObservableObject {
    @Published var buttonTapped = false // 仅标记按钮是否被点击,用于显示错误提示
}

struct ButtonView: View {
    @ObservedObject var progress: UserProgress
    var onTap: () -> Void // 点击回调,让父视图处理校验和导航逻辑
    
    var body: some View {
        Button("Button title") {
            progress.buttonTapped = true
            onTap()
        }
    }
}

struct TextView: View {
    @Binding var textValue: String
    let placeholder: String // 增加占位符参数,区分两个输入框
    
    var body: some View {
        TextField(placeholder, text: $textValue)
    }
}

struct mainViewApp: View {
    @StateObject var progress = UserProgress()
    @State var readyToNavigate: Bool = false
    @State var text1Value = ""
    @State var text2Value = ""
    
    // 校验逻辑:检查两个输入框是否都不为空
    private func validateAndNavigate() {
        guard !text1Value.isEmpty, !text2Value.isEmpty else {
            return
        }
        readyToNavigate = true
    }
    
    var body: some View {
        NavigationStack {
            VStack {
                Text("输入1内容:\(text1Value)")
                TextView(textValue: $text1Value, placeholder: "请输入内容1")
                if progress.buttonTapped && text1Value.isEmpty {
                    Text("ERROR1:输入1不能为空")
                        .foregroundColor(.red)
                }
                
                Text("输入2内容:\(text2Value)")
                TextView(textValue: $text2Value, placeholder: "请输入内容2")
                if progress.buttonTapped && text2Value.isEmpty {
                    Text("ERROR2:输入2不能为空")
                        .foregroundColor(.red)
                }
                
                ButtonView(progress: progress, onTap: validateAndNavigate)
            }
            .padding()
            .navigationBarTitle("主菜单", displayMode: .inline)
            .navigationDestination(isPresented: $readyToNavigate) {
                Text("跳转成功!这里是下一页")
            }
            .toolbarColorScheme(.dark, for: .navigationBar)
            .toolbarBackground(Color.black, for: .navigationBar)
            .toolbarBackground(.visible, for: .navigationBar)
        }
    }
}

struct test_Previews: PreviewProvider {
    static var previews: some View {
        mainViewApp()
    }
}

关键修改说明

  • 共享状态实例:ButtonView通过@ObservedObject接收父视图传递的UserProgress实例,确保状态变化能同步到父视图。
  • 拆分输入状态:两个输入框的内容由mainViewApp的@State变量分别管理,避免互相覆盖,校验逻辑能直接获取准确值。
  • 回调处理逻辑:按钮点击后通过onTap回调通知父视图执行校验,校验通过后更新readyToNavigate触发导航。
  • 简化状态管理:UserProgress仅保留按钮点击标记,用于控制错误提示的显示,职责更单一。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:25:23