在iOS 13上默认显示系统Emoji键盘

21

解决方案

这是一个完整的解决方案/工作方法,可以解决这个问题,请同时为Blld的答案投票,因为这是所需的关键信息!

替代标题以辅助搜索

  • 将表情符号键盘显示为UIKeyInput对象的默认键盘(在iOS 13中)
  • 强制iOS 13显示表情符号键盘
  • UITextInputMode.primaryLanguage设置为表情符号
  • 通过编程方式将键盘设置为表情符号

之前,返回与primaryLanguage等于“emoji”的UITextInputMode会默认显示表情符号键盘(请参见下图)。

Emoji keyboard screen shot

返回“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上运行此代码将设置键盘为系统Emoji键盘,但在iOS 13上没有影响。这是已知的错误吗?是否有解决方法?
更新:
- @Navillus提出的“活动输入模式”完整列表为:“en-GB”,“emoji” - 在13.0、13.1、13.1.1、13.1.2和13.2(种子1)上进行了测试并确认。

有趣的事情:我能够在模拟器上成功运行这段代码,但在设备上却不能。两者都是iOS 13。现在我很好奇。 - Marina Aguilar
在模拟器中对我有效。@rjstelling 您的设备上的 activeInputModes 的完整列表是什么?您可以使用以下命令进行检查: print(UITextInputMode.activeInputModes.map({ (m) -> String in return m.primaryLanguage ?? "" })) - Navillus
@Navillus - 答案在问题中,它是“en-GB”和“emoji”。 - Richard Stelling
2
这个问题现在已经在iOS 13.4 / Xcode 11.4中得到了修复。 - Stephen
4个回答

10

我因为有一个双语的日语/英语应用程序,对iOS 13提出了一个雷达。一些字段是日语,一些是英语,因此显然向用户呈现正确的键盘类型比让他们来回翻转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中,这个bug没有被修复,但是他们阻止了我的解决方法。

很好。我不会再向他们报告任何错误。如果我找到了解决方法,我只会使用它。

因此,看起来他们现在正在默默地禁用此功能。而且这是一个功能,这是这个方法调用的文字目的,以找出应该向用户呈现什么输入模式。

如果您有另一种语言并想选择英语,它仍然可以正常工作。

所以,如果我的用户将日语设置为键盘选择,则可以强制使用英语键盘。反之则不行。任何尝试获取日语输入模式的尝试都会以英语键盘结束。

编辑:

还有另一条路径可以解决这个问题,但涉及发现和使用内部API,这并不简单。您必须找到用于管理点击地球按钮结果的函数。如果您这样做,您就相当于模拟了用户的轻敲,它具有广泛的影响,也就是说,键盘也会为其他应用程序进行更改。因此,它不建议使用,100%会失败App Store提交。因为我上次解决问题的结果,我不想发布它。

我认为很难很容易地理解苹果。我所知道的是:

  1. API的功能未按照说明书运作
  2. 已经报告过了,但他们没有修复这个bug
  3. 自从报告以来,他们打破了(有意或无意地)解决办法

因此,未来的解决方法应该被保存,直到他们的意图变得清晰和/或他们修复了这个错误(这就是他们应该做的)。撤销部分API而不发布更改是一个重大的错误。


1
谢谢!这帮助我更好地理解了。我怀疑他们并没有故意阻止你的解决方法,这更像是一个 bug。如果他们想要删除该功能,他们本可以将其弃用。 - Richard Stelling
永远不要将那些可以用愚蠢来解释的事情归因于恶意。 - Richard Stelling

10

2
这对我在iOS 13上有效。只需在我的自定义UITextField中为textInputContextIdentifier返回“emoji”“”,即可显示Emoji键盘(与问题中的textInputMode覆盖组合使用)。感谢您提供隐藏文档的提示。 - Baza207
当应用程序的本地化为阿拉伯语时,如果我们想强制一个UITextField使用英语小数键盘,则不起作用。 - shujaat

10

NB:确保您已启用Emoji键盘。

这似乎是iOS 13的一个bug,对于设备而言(不影响模拟器),解决方法是覆盖textInputContextIdentifier属性并返回非空值。

//
//  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
    }
}

感谢 blld 提供的答案。

1
我在显示英文小数键盘方面遇到了同样的问题。我的应用程序语言是阿拉伯语,我想让文本字段显示英文小数键盘。我已经通过覆盖这些变量和方法来完成了上述步骤。在textInputMode中,我只返回“en-US”模式,但在iOS 13中仍然显示阿拉伯小数键盘。 - shujaat
我可以确认,在iOS 13.2上似乎不再起作用了... - Jay Lee
@JayLee 请确保您已启用表情符号键盘。 - Richard Stelling

1

简单做

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()
        }
    }
}

对我来说,所接受的答案在UIButton上没有起作用,但UITextField的确工作良好。 - Christian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接