You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何为UITextField的自定义输入视图添加OTP视图并在自定义数字键盘中集成自动捕获OTP功能

实现自定义数字键盘的OTP视图集成与自动捕获功能

嘿,这两个需求其实在iOS开发里挺常见的,我帮你一步步拆解实现:

一、给自定义数字键盘添加OTP视图

首先咱们得把OTP输入/展示区域整合到你现有的MyCustomInputView里。一般OTP视图是由4-6个小输入框(或UILabel)组成的横向布局,用来接收用户的验证码输入。

1. 在MyCustomInputView中集成OTP视图

先在自定义输入视图类里添加OTP视图的属性,然后完成布局:

class MyCustomInputView: UIView {
    // 保留你原有的数字键盘按钮、代理等属性
    weak var delegate: MyCustomInputViewDelegate?
    
    // 新增OTP视图(假设你已经封装了OTPInputView)
    let otpView = OTPInputView(frame: .zero)
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupOTPView()
        setupNumberKeyboard() // 你原有的数字键盘布局方法
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupOTPView()
        setupNumberKeyboard()
    }
    
    private func setupOTPView() {
        // 将OTP视图添加到自定义键盘顶部,调整布局参数适配你的需求
        addSubview(otpView)
        otpView.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            otpView.topAnchor.constraint(equalTo: topAnchor, constant: 20),
            otpView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
            otpView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
            otpView.heightAnchor.constraint(equalToConstant: 50)
        ])
        
        // 设置OTP视图的代理,用来接收输入回调
        otpView.delegate = self
    }
}

2. 处理OTP视图的输入回调

MyCustomInputView扩展实现OTP视图的代理方法,同步输入内容到关联的UITextField:

// 假设你的OTPInputView定义了如下代理协议
protocol OTPInputViewDelegate: AnyObject {
    func otpInputViewDidComplete(_ view: OTPInputView, code: String)
    func otpInputViewDidChange(_ view: OTPInputView, currentText: String)
}

extension MyCustomInputView: OTPInputViewDelegate {
    func otpInputViewDidComplete(_ view: OTPInputView, code: String) {
        // 通知代理完成输入
        delegate?.customInputViewDidFinishOTPInput(code: code)
        // 同步内容到绑定的UITextField
        if let textField = self.superview?.superview as? UITextField {
            textField.text = code
        }
    }
    
    func otpInputViewDidChange(_ view: OTPInputView, currentText: String) {
        // 实时同步内容到UITextField
        if let textField = self.superview?.superview as? UITextField {
            textField.text = currentText
        }
    }
}

3. 关联数字键盘按钮与OTP视图

在你原有的数字键盘按钮点击事件里,把输入的数字传递给OTP视图:

extension MyCustomInputView {
    // 数字按钮点击方法
    @objc private func numberButtonTapped(_ sender: UIButton) {
        guard let number = sender.titleLabel?.text else { return }
        otpView.addCharacter(number)
    }
    
    // 删除按钮点击方法
    @objc private func deleteButtonTapped(_ sender: UIButton) {
        otpView.deleteLastCharacter()
    }
}

这里的addCharacter(_:)deleteLastCharacter()需要你在OTPInputView里实现,逻辑是:输入数字时填充到下一个空输入框,删除时清空当前输入框并跳回上一个。


二、集成自动捕获OTP功能

iOS里自动捕获验证码有两种主流实现方式,推荐优先用系统原生的自动填充,无需额外权限体验更好。

方式一:系统原生自动填充(iOS12+,推荐)

  1. 给你的UITextField设置textContentTypeoneTimeCode,让系统识别短信中的验证码:
textField.textContentType = .oneTimeCode
  1. 监听UITextField的文本变化,把系统自动填充的验证码同步到OTP视图:
class YourViewController: UIViewController {
    @IBOutlet weak var textField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        let inputView = MyCustomInputView()
        textField.inputView = inputView
        inputView.delegate = self
        
        // 开启自动填充支持
        textField.textContentType = .oneTimeCode
        
        // 监听文本变化事件
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(textFieldTextDidChange(_:)),
            name: UITextField.textDidChangeNotification,
            object: textField
        )
    }
    
    @objc private func textFieldTextDidChange(_ notification: Notification) {
        guard let textField = notification.object as? UITextField,
              let code = textField.text,
              !code.isEmpty else { return }
        
        // 同步验证码到自定义键盘的OTP视图
        if let customInputView = textField.inputView as? MyCustomInputView {
            customInputView.otpView.setCode(code)
        }
    }
}
  1. OTPInputView里实现setCode(_:)方法,把验证码填充到对应的输入框中。

方式二:监听短信通知(iOS10+,需要通知权限)

如果系统自动填充无法满足需求,可以通过监听短信通知提取验证码:

  1. 先请求用户的通知权限:
import UserNotifications

class YourViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 请求通知权限
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound]) { granted, error in
            if granted {
                DispatchQueue.main.async {
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }
        UNUserNotificationCenter.current().delegate = self
    }
}
  1. 实现通知代理方法,提取短信中的验证码:
extension YourViewController: UNUserNotificationCenterDelegate {
    func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
        completionHandler([.banner])
        
        // 提取短信内容
        let smsContent = notification.request.content.body
        // 用正则匹配6位数字验证码(根据你的实际验证码位数调整)
        let regexPattern = "\\d{6}"
        guard let regex = try? NSRegularExpression(pattern: regexPattern),
              let match = regex.firstMatch(in: smsContent, range: NSRange(location: 0, length: smsContent.count)) else { return }
        
        let code = (smsContent as NSString).substring(with: match.range)
        // 填充到OTP视图
        DispatchQueue.main.async {
            if let customInputView = self.textField.inputView as? MyCustomInputView {
                customInputView.otpView.setCode(code)
            }
        }
    }
}

注意:这种方式需要用户授权通知权限,且要适配不同运营商的短信格式,正则表达式可能需要调整。


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

火山引擎 最新活动