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

SwiftUI:iOS端检测数字键盘删除键按下(空文本场景)

实现iOS数字键盘删除键响应(含文本为空场景)

由于SwiftUI原生的.onKeyPress仅支持硬件键盘和macOS,而.onChange无法捕获文本为空时的删除键操作(因为文本值没有变化),我们可以通过封装UIKit的UITextField来实现需求,核心思路是利用UIKit原生的文本输入回调机制。

步骤1:自定义支持删除键回调的UITextField子类

重写deleteBackward()方法,该方法会在用户按下软键盘删除键时触发(无论文本是否为空):

class DeleteAwareTextField: UITextField {
    // 定义删除键按下的回调闭包
    var onDeleteBackward: (() -> Void)?
    
    override func deleteBackward() {
        super.deleteBackward() // 保留原有删除逻辑
        onDeleteBackward?() // 触发自定义回调
    }
}

步骤2:封装为SwiftUI可用的View

通过UIViewRepresentable将自定义UITextField包装成SwiftUI组件,同时处理文本绑定、数字键盘配置和输入过滤:

struct NumberTextField: UIViewRepresentable {
    @Binding var text: String
    // 外部传入的删除键回调
    var onDeleteBackward: () -> Void
    
    func makeUIView(context: Context) -> DeleteAwareTextField {
        let textField = DeleteAwareTextField()
        textField.keyboardType = .numberPad // 设置数字键盘
        textField.delegate = context.coordinator
        textField.onDeleteBackward = onDeleteBackward // 绑定回调
        return textField
    }
    
    func updateUIView(_ uiView: DeleteAwareTextField, context: Context) {
        // 同步SwiftUI的文本状态到UITextField
        if uiView.text != text {
            uiView.text = text
        }
    }
    
    // 创建协调器处理UITextField代理逻辑
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UITextFieldDelegate {
        var parent: NumberTextField
        
        init(_ parent: NumberTextField) {
            self.parent = parent
        }
        
        // 过滤非数字输入
        func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
            let allowedCharacters = CharacterSet.decimalDigits
            let characterSet = CharacterSet(charactersIn: string)
            return allowedCharacters.isSuperset(of: characterSet)
        }
        
        // 同步UITextField的文本变化到SwiftUI
        func textFieldDidChangeSelection(_ textField: UITextField) {
            parent.text = textField.text ?? ""
        }
    }
}

步骤3:在SwiftUI视图中使用

直接调用封装好的NumberTextField,并在回调中处理文本为空时的删除键逻辑:

struct ContentView: View {
    @State private var inputText = ""
    
    var body: some View {
        VStack(spacing: 20) {
            NumberTextField(text: $inputText) {
                // 删除键按下时的逻辑
                if inputText.isEmpty {
                    print("文本为空,删除键被触发")
                    // 这里添加你的自定义操作,比如切换到上一个输入框、触发特定事件等
                } else {
                    print("删除键按下,当前文本:\(inputText)")
                }
            }
            .padding()
            .border(Color.gray)
            
            Text("当前输入:\(inputText)")
        }
        .padding()
    }
}

方案说明

  • 该方案通过UIKit的原生API捕获软键盘删除键事件,不受文本是否为空的限制;
  • 自定义DeleteAwareTextField的deleteBackward()方法是核心,确保所有删除键操作都能被捕获;
  • 协调器(Coordinator)负责处理文本同步和输入过滤,保证组件的SwiftUI风格使用体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:05:20