Apple introduced Keyboard Extension in iOS 8, but there is little information about it on the Internet. I also encountered a lot of problems in the development, so I wrote this article in order to share this knowledge with you. Custom Keyboard is also very simple to implement, we just need to create a Custom Keyboard Extension Target in our project, Xcode will automatically create a KeyboardViewController for us, Developers can do simple development with this class. But it’s not always that simple. We may need to request network data at the keyboard, or communicate with Containing App, etc. At this time, we will encounter many problems. In this article, I will describe common problem solving techniques.


The profile

  • How to communicate with Extension
  • Check whether the keyboard has been added
  • Check whether the keyboard is active
  • Play system Sound
  • Checks whether RequestsOpenAccess has been obtained
  • Keyboard switching method

How to communicate with Extension

This is an official picture provided by Apple. Containing App is our main App, and Host App is the third-party App (such as wechat) run by Extension. In order to facilitate understanding, we will call the Containing App “main App” below. Host apps are called third-party apps.

The summary is as follows:

  1. The App Extension cannot communicate directly with the main App (simply understand that they are two different processes, the extension started does not mean that the main App will also start).
  2. An App Extension can communicate with the main App via the Open URL, but the link is only one-way (because App Extension doesn’t have one)openURLSuch as the entry to receive messages)
  3. The main App and App Extension can communicate by reading and writing common file resources (such as UserDefault, if added to the same file)AppGroups
  4. Another method not mentioned officially: you can use DarwinNotify to establish communication between Extension and Containing app. You can refer to 👇 open source library below

choefele/CCHDarwinNotificationCenter

Maintaining UserDefault through App Groups is an easy way to communicate. However, developers should also pay attention to the fact that if our keyboard does not obtain full access, the keyboard can only read and cannot modify the value of UserDefault (if the UserDefault is created by Containing app). Another point is that DarwinNotify now requires full access as well.

Finally, I give you a piece of advice: be sure to debug on the real machine!

Check whether the keyboard has been added

var isKeyboardEnabled: Bool {
  guard let keyboards = UserDefaults.standard.object(forKey: "AppleKeyboards") as? [String] else {
    return false
  }
  return keyboards.contains("Your extension bundle ID")}Copy the code

Check whether the keyboard is active

There is often a requirement for Keyboard applications: when users switch to the Keyboard developed by us for the first time, they need to display the welcome 👏 text in the main App or start the boot process. We can notify the main App via openURL.

// Open the main APP, such as openURL(scheme:"yourAppScheme://actived")
func openURL(scheme: String) {
  let url = URL(string: scheme)!
  let context = NSExtensionContext()
  context.open(url, completionHandler: nil)
  var responder = self as UIResponder?
  let selectorOpenURL = sel_registerName("openURL:")
  while(responder ! = nil) {ifresponder! .responds(to: selectorOpenURL) { responder! .perform(selectorOpenURL, with: url)break} responder = responder? Func application(_ app: UIApplication, open url: url, options:) func application(_ app: UIApplication, open url: url, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {if url.scheme == "yourAppScheme" && url.host == "actived" {
    // do something
  }
  return true
}
Copy the code

The important thing to note here is that openURL will call up the main App (if the main App is not in the foreground), so extra judgment is required here.

Play system Sound

// Go directly to the code
// Click SystemSoundID = 1123
// Delete button: SystemSoundID = 1155
// System keyboard: SystemSoundID = 1156
AudioServicesPlaySystemSound(SystemSoundID)
Copy the code

Checks whether RequestsOpenAccess has been obtained

// Keyboard Extension
override var hasFullAccess: Bool {
  if #available(iOS 11.0, *) {
    return super.hasFullAccess// super is UIInputViewController.
  }
  if #available(iOS 10.0, *) {
    let original: String? = UIPasteboard.general.string
    UIPasteboard.general.string = ""
    let val: Bool = UIPasteboard.general.hasStrings
    if let str = original {
      UIPasteboard.general.string = str
    }
    return val
  }
  return UIPasteboard.general.isKind(of: UIPasteboard.self)}Copy the code

There’s no way to get it directly from the main App, but you can use the communication method mentioned above to upload status in Keyboard Extension

Full screen hidden switch keyboard key

In full screen, the device system will provide us with a switch keyboard button by default, so the keyboard we developed does not need to provide this button. We can judge by the following ways:

// needsInputModeSwitchKey
var needsSwitchKey: Bool {
	if #available(iOSApplicationExtension 11.0, *) {
		return needsInputModeSwitchKey
	} else {
		return true}}Copy the code

Other information

Custom Keyboard

Custom Keyboards – Extensions – iOS – Human Interface Guidelines – Apple Developer

For attention, please like 👍