iOS 13 默认显示系统表情符号键盘

Showing the system Emoji keyboard by default on iOS 13

解决方案

这里还有一个 around for this issue, please up vote Blld's 因为这是所需的重要信息!

辅助搜索的替代标题

返回 UITextInputModeprimaryLanguage 之前等于 "emoji" 将默认显示表情符号键盘(见下图)。

返回 "emoji" UITextInputMode.

的示例代码
//
//  ViewController.swift
//  Keyboard Info
//
//  Created by Richard Stelling on 30/09/2019.
//  Copyright © 2019 Richard Stelling. All rights reserved.
//

import UIKit

class TestButton: UIButton, UIKeyInput {

    var hasText: Bool = true

    func insertText(_ text: String) { print("\(text)") }

    func deleteBackward() {}


    override var canBecomeFirstResponder: Bool { return true }

    override var canResignFirstResponder: Bool { return true }

    override var textInputMode: UITextInputMode? {
        for mode in UITextInputMode.activeInputModes {
            if mode.primaryLanguage == "emoji" {
                return mode
            }
        }
        return nil
    }
}

运行 iOS 12 上的此代码会将键盘设置为系统表情符号键盘,但在 iOS 13 上它没有任何影响。

这是一个已知错误吗?有解决方法吗?

更新

我为 iOS 13 提交了雷达,因为我有一个双语 Japanese/English 应用程序。有些字段是日文的,有些是英文的,因此显然向用户显示正确的键盘类型而不是让它们来回翻转 20 次是有意义的。

对此有一个解决方法,那就是在 UIKit 调用 'textInputMode' 之后,您可以在主线程中这样做:

// has to be done after the textInputMode method is called
if #available(iOS 13, *) {
    textField.keyboardType = textField.keyboardType
} 

这会强制键盘在用您想要的 textInputMode 回答后重新加载。我向他们通报了这个错误,以及获得正确行为的解决方法。

所以在 iOS 13.1 中,错误没有修复,但是他们阻止了我的解决方法。

不错。我不会再向他们报告任何错误。相反,如果我找到解决方法,我会直接使用它。

看来他们现在正在默默地禁用此功能。这是一个功能,这就是这个方法调用的目的,找出应该呈现给用户的输入模式。

仍然可以正常工作 但如果你有另一种语言并且想要 select 英语。

因此,如果我的用户将日语设置为键盘 selection,那么我可以强制启用英语键盘。只是不是相反。任何获得日语输入模式的尝试都以英语键盘结束。

编辑:

您可以通过另一条途径解决此问题,但它涉及发现和使用内部 API,这并不简单。您基本上必须找到用于管理点击地球按钮结果的函数。如果你这样做,你实际上是在模拟用户的点击,它具有广泛的影响,也就是说,键盘也会为其他应用程序而改变。所以不推荐,100%会App Store提交失败。由于我上次解决方法的结果,我不想 post 它。

我认为要理解苹果不是那么容易。我只知道:

  1. API 未按发布的方式运行
  2. 已报告但他们没有修复错误
  3. 自报告之时起,他们就(有意或无意)破坏了解决方法

因此,在他们的意图明确之前,应该保留未来的变通办法 and/or 他们修复了这个错误(这是他们应该做的)。简单地撤销部分 API 而不发布更改是一个主要错误。

您需要在 textField 上设置 textinputcontextidentifier 以便 iOS 知道在哪里保存自定义 textInputMode

它没有写在文档中,但它有效。

参考:https://developer.apple.com/documentation/uikit/uiresponder/1621091-textinputcontextidentifier

NB: Make sure you have the Emoji keyboard enabled.

这似乎是一个 iOS 13 错误,解决方法(对于设备,这不会影响模拟器)是覆盖 textInputContextIdentifier 属性 和 return 一个非零值。

//
//  ViewController.swift
//  Keyboard Info
//
//  Created by Richard Stelling on 30/09/2019.
//  Copyright © 2019 Richard Stelling. All rights reserved.
//

import UIKit

class TestButton: UIButton, UIKeyInput {

    var hasText: Bool = true

    override var textInputContextIdentifier: String? { "" } // return non-nil to show the Emoji keyboard ¯\_(ツ)_/¯ 

    func insertText(_ text: String) { print("\(text)") }

    func deleteBackward() {}

    override var canBecomeFirstResponder: Bool { return true }

    override var canResignFirstResponder: Bool { return true }

    override var textInputMode: UITextInputMode? {
        for mode in UITextInputMode.activeInputModes {
            if mode.primaryLanguage == "emoji" {
                return mode
            }
        }
        return nil
    }
}

Thanks to blld for his answer.

简单做

class EmojiTextField: UITextField {

   // required for iOS 13
   override var textInputContextIdentifier: String? { "" } // return non-nil to show the Emoji keyboard ¯\_(ツ)_/¯ 

    override var textInputMode: UITextInputMode? {
        for mode in UITextInputMode.activeInputModes {
            if mode.primaryLanguage == "emoji" {
                return mode
            }
        }
        return nil
    }

override init(frame: CGRect) {
        super.init(frame: frame)

        commonInit()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)

         commonInit()
    }

    func commonInit() {
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(inputModeDidChange),
                                               name: UITextInputMode.currentInputModeDidChangeNotification,
                                               object: nil)
    }

    @objc func inputModeDidChange(_ notification: Notification) {
        guard isFirstResponder else {
            return
        }

        DispatchQueue.main.async { [weak self] in
            self?.reloadInputViews()
        }
    }
}