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

iOS键盘扩展:如何检测当前激活文本框的输入类型?

Fixing UITextDocumentProxy Nil Values for iOS Keyboard Extensions

Hey there! I’ve dealt with this exact headache when building custom iOS keyboard extensions—those nil values for textContentType and keyboardType can feel like a dead end. Let’s walk through why this happens and how you can work around it to show that "@" button when needed.

Why Are These Properties Returning Nil?

  • Host App Limitations: Not all apps (including some system apps like Messages) expose textContentType or keyboardType to keyboard extensions. Some developers skip setting these traits, and certain system input fields restrict access for privacy or design reasons.
  • Timing Issues: Trying to access these properties too early (like in textWillChange) might mean the proxy hasn’t fully initialized the values yet.

Practical Workarounds

1. Infer Input Type from Context Text

Since direct access isn’t always reliable, use the surrounding text to guess the input field’s purpose. For Messages’ address field, you can look for context clues like "To:", "收件人", or existing "@" characters:

override func textDidChange(_ textInput: UITextInput?) {
    super.textDidChange(textInput)
    
    let beforeContext = textDocumentProxy.documentContextBeforeInput ?? ""
    let afterContext = textDocumentProxy.documentContextAfterInput ?? ""
    
    // Check for address/recipient field clues
    let isRecipientField = beforeContext.contains("To:") 
        || beforeContext.contains("收件人") 
        || beforeContext.contains("@") 
        || afterContext.contains("@")
    
    // Toggle your "@" button based on the check
    if isRecipientField {
        showAtButton() // Replace with your button show logic
    } else {
        hideAtButton() // Replace with your button hide logic
    }
}

This method isn’t 100% foolproof, but it works surprisingly well for most common system and third-party app scenarios.

2. Check Properties at the Right Lifecycle Point

Sometimes the values just aren’t ready when textWillChange fires. Try accessing keyboardType or textContentType in the didBecomeActive method, which triggers when your keyboard becomes the active input method:

override func didBecomeActive() {
    super.didBecomeActive()
    
    // Check keyboard type first if available
    if let keyboardType = textDocumentProxy.keyboardType {
        if keyboardType == .emailAddress {
            showAtButton()
            return
        }
    }
    
    // Fall back to context check if keyboard type is nil
    let beforeContext = textDocumentProxy.documentContextBeforeInput ?? ""
    if beforeContext.contains("To:") || beforeContext.contains("收件人") {
        showAtButton()
    }
}

This combines direct property checks with context inference for better coverage.

3. Combine Multiple Checks for Reliability

For the best results, layer your checks: first try textContentType/keyboardType, then fall back to context analysis. This way you cover cases where the host app does expose the traits, and cases where it doesn’t.

Final Notes

  • Test across multiple apps: System apps like Mail might expose textContentType = .emailAddress, while Messages’ recipient field won’t—so your context check will be the fallback here.
  • Be flexible: Some third-party apps might have unique context clues, so you can expand your check logic as you test more scenarios.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:57:59