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

SwiftUI 如何监听TextField回车键事件并按输入匹配结果展示不同图标

解决方案

方案1:iOS 15+ 原生实现(推荐)

SwiftUI 从 iOS 15 开始提供了原生的onSubmit修饰符,专门用于监听输入框的回车键触发事件,完全符合你的需求,你可以直接替换原来的onReceive逻辑,步骤如下:

  1. 新增状态变量控制结果图标的展示
  2. 给TextField添加onSubmit修饰符,回车时触发答案校验
  3. 根据校验结果展示对应图标

修改后的完整代码:

struct QuestionItemView: View {
    @State private var question: Question?
    @State private var answer = ""
    // 新增状态:nil=不显示图标,true=答案正确,false=答案错误
    @State private var isAnswerCorrect: Bool? = nil

    var body: some View {
        VStack(spacing: 30) {
            GroupBox {
                if let question = question {
                    Text(question.question)
                        .font(.largeTitle)
                        .fontWeight(.heavy)
                        .scaledToFit()
                        .frame(width: 300, height: 100)
                        .cornerRadius(12)
                }
            }
        
            GroupBox {
                TextField("Enter your answer", text: $answer)
                    .frame(width: 300)
                    .font(.title2)
                    .scaledToFit()
                    .cornerRadius(12)
                    .multilineTextAlignment(.center)
                    // 监听回车键事件
                    .onSubmit {
                        guard let correctAnswer = question?.answer else { return }
                        // 自动去除输入前后的空格换行,避免输入误判
                        isAnswerCorrect = (answer.trimmingCharacters(in: .whitespacesAndNewlines) == correctAnswer)
                        // 如果需要回车后清空输入/切换下一题,可以在这里加逻辑
                        // 例如:
                        // DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                        //     answer = ""
                        //     isAnswerCorrect = nil
                        //     question = Bundle.main.decode("questions.json").randomElement()
                        // }
                    }
           }
            
            // 展示结果图标
            if let result = isAnswerCorrect {
                Image(systemName: result ? "checkmark.circle.fill" : "xmark.circle.fill")
                    .foregroundColor(result ? .green : .red)
                    .font(.system(size: 60))
            }
        } //: VStack
        .frame(width: 240)
        .background(RoundedRectangle(cornerRadius: 7.0).fill(Color.white))
        .onAppear {
            let questions: [Question] = Bundle.main.decode("questions.json")
            question = questions.randomElement()
        }
    }
}

方案2:兼容 iOS 15 以下版本

如果需要适配更低系统版本,可以通过桥接 UIKit 的UITextField实现回车键监听,核心是通过UITextFieldDelegate的textFieldShouldReturn方法捕获回车事件,示例封装如下:

struct ReturnKeyMonitorTextField: UIViewRepresentable {
    @Binding var text: String
    let placeholder: String
    let onReturn: () -> Void
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.placeholder = placeholder
        textField.text = text
        textField.delegate = context.coordinator
        textField.textAlignment = .center
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(text: $text, onReturn: onReturn)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        @Binding var text: String
        let onReturn: () -> Void
        
        init(text: Binding<String>, onReturn: @escaping () -> Void) {
            self._text = text
            self.onReturn = onReturn
        }
        
        func textFieldDidChangeSelection(_ textField: UITextField) {
            text = textField.text ?? ""
        }
        
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            textField.resignFirstResponder()
            onReturn()
            return true
        }
    }
}

使用时直接替换原来的TextField即可:

ReturnKeyMonitorTextField(text: $answer, placeholder: "Enter your answer", onReturn: {
    guard let correctAnswer = question?.answer else { return }
    isAnswerCorrect = (answer.trimmingCharacters(in: .whitespacesAndNewlines) == correctAnswer)
})
.frame(width: 300)
.font(.title2)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.15 22:06:02