Отображение системной клавиатуры Emoji по умолчанию на iOS 13
Решение
Вот полное решение / обход этой проблемы, пожалуйста, проголосуйте за ответ Blld, потому что это была жизненно важная необходимая информация!
Альтернативные названия для облегчения поиска
- Отображение клавиатуры Emoji по умолчанию для объекта UIKeyInput (в iOS 13)
- Заставить iOS 13 отображать клавиатуру Emoji
- Установка
UITextInputMode.primaryLanguage
смайлики - Программно настроить клавиатуру на эмодзи
До ios13 возвращениеUITextInputMode
с участием primaryLanguage
со значением "эмодзи" по умолчанию будет отображаться клавиатура эмодзи (см. изображение ниже).
Пример кода для возврата "смайлика" 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)
4 ответа
NB: убедитесь, что у вас включена клавиатура Emoji.
Похоже, это ошибка iOS 13, решение (для устройств это не влияет на симулятор) заключается в том, чтобы переопределить 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 за его ответ.
Я сообщил об этом для 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 ошибка не была исправлена, однако они заблокировали мой обходной путь.
Приятно. Я больше не буду сообщать им об ошибках. Скорее, если я найду обходной путь, я просто воспользуюсь им.
Похоже, теперь они молча отключают эту функцию. И это функция, это буквально цель вызова этого метода, чтобы узнать, какой режим ввода должен быть представлен пользователю.
Он по- прежнему работает нормально, если у вас есть другой язык и вы хотите выбрать английский.
Поэтому, если мой пользователь устанавливает японский язык в качестве выбора клавиатуры, я могу принудительно включить английскую клавиатуру. Только не наоборот. Любые попытки получить японский режим ввода заканчиваются на английской клавиатуре.
РЕДАКТИРОВАТЬ:
Есть еще один путь, который можно обойти, но он включает обнаружение и использование внутреннего API, что непросто. По сути, вам нужно будет найти функции, используемые для управления результатами нажатия кнопки глобуса. Если вы сделаете это, вы, по сути, имитируете нажатия пользователя, и это будет иметь широкий спектр эффектов, то есть клавиатура будет изменена и для других приложений. Так что это не рекомендуется, 100% не удастся отправить в App Store. Я не хочу публиковать его из-за результатов моего последнего обходного пути.
Я думаю, что сложно понять Apple. Все, что я знаю, это то, что:
- API не работает так, как опубликовано
- было сообщено, и они не исправили ошибку
- с момента сообщения они нарушили (намеренно или нет) обходной путь
Так что будущие обходные пути следует накапливать до тех пор, пока их намерения не будут ясны и / или они не исправят эту ошибку (что им и следует делать). Простой отзыв части API без публикации изменений - серьезная ошибка.
Вам нужно установить textinputcontextidentifier
в текстовом поле, чтобы iOS знала, где сохранить настраиваемый textInputMode
В документе это не написано, но работает.
ссылка: https://developer.apple.com/documentation/uikit/uiresponder/1621091-textinputcontextidentifier
сделать просто
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()
}
}
}