Отображение системной клавиатуры 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. Все, что я знаю, это то, что:

  1. API не работает так, как опубликовано
  2. было сообщено, и они не исправили ошибку
  3. с момента сообщения они нарушили (намеренно или нет) обходной путь

Так что будущие обходные пути следует накапливать до тех пор, пока их намерения не будут ясны и / или они не исправят эту ошибку (что им и следует делать). Простой отзыв части 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()
        }
    }
}
Другие вопросы по тегам