iOS 8 brings a lot of cool features along with it. One of them being the addition of 3rd Party Keyboards as App Extensions. And we should really pay attention this time, as it opens up a whole new category of apps and monetization options. With over a million apps in the Store, I will welcome a new category any day 🙂

With this post, I want to show you how to create a Custom Keyboard for your app which can be used system-wide as a keyboard option.

This sample tutorial will be done in Swift. It was my first real project using the Swift language and I’m loving it.. “for now”. Let’s jump right in.

First off, here is a screenshot of what we are going to end up building. The keyboard will be able to enter text into a text field, delete text and some other basic functions. Advanced features like predictive text, Lexicons, emoji etc and out of the scope of this tutorial. This project will posted on Github soon.

kb

Click here to download the sample Xcode project

Create Your Xcode Project

Open up Xcode 6 and create a new project. File->New->Project.

Give your project the name CustomKeyboardSample and save it in a suitable location. This is going to be our host project, we still need to add an extension.

For now, lets add a Text Field to the project. Open the Storyboard called Main.Storyboard and drag a UITextField to the view controller on the stage.

screen0

This is where we are going to be testing our inputs. Now it is time to add our extension

Click on File-> New -> Target, select Custom Keyboard which is listed under iOS/Application Extension. Give it the name CustomKeyboard and select, the Swift language.

screen1

Now you should have a folder called CustomKeyboard as the new target, with a file called KeyboardViewController.swift. Xcode has added some initial code in for us and this keyboard should be ready to go (albeit with no functionality yet)…

You can now try running the CustomKeyboardSample app and try out your new keyboard.

When you tap in the text field, the system keyboard will show up. We can switch keyboards using the Globe icon in the bottom row, but we need to install our new keyboard before it will show up.

Click here to download the sample Xcode project

Go to the Home screen. (Click on the Menu bar, Hardware->Home). Open the Settings app and navigate to General-Keyboard-Keyboards. Tap on “Add New Keyboard” and select CustomKeyboard. Turn on the switch to enable it and accept the warning message.

Tap done and you are are ready to go.

If run the app again in the simulator, you will now be able to switch the keyboard. Tap the Globe icon until you see a keyboard with just the “Next Keyboard” button.

Now it is time to start adding our own keys.

Open the file KeyboardViewController.h . In this file, you will see a class KeyboardViewController which inherits from UIInputViewController. This is the class that manages the view for the keyboard. We can add out buttons to the containing view and it will show up in the keyboard.

Add a function called createButton

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
func createButtonWithTitle(title: String) -> UIButton {
 
        let button = UIButton.buttonWithType(.System) as UIButton
        button.frame = CGRectMake(0, 0, 20, 20)
        button.setTitle(title, forState: .Normal)
        button.sizeToFit()
        button.titleLabel.font = UIFont.systemFontOfSize(15)
        button.setTranslatesAutoresizingMaskIntoConstraints(false)
        button.backgroundColor = UIColor(white: 1.0, alpha: 1.0)
        button.setTitleColor(UIColor.darkGrayColor(), forState: .Normal)
 
        button.addTarget(self, action: "didTapButton:", forControlEvents: .TouchUpInside)
 
        return button
    }

In the code above, we are going to add a button programmatically and set its properties. We could have used nibs but with the sheer number of buttons we are going to have to manage, this is a better option.

The code will call a method called didTapButton when the button is tapped. So let’s add that method now.

1
2
3
4
5
6
7
8
func didTapButton(sender: AnyObject?) {
 
        let button = sender as UIButton
        let title = button.titleForState(.Normal)
        var proxy = textDocumentProxy as UITextDocumentProxy
 
        proxy.insertText(title)
    }

In the method above, we implement the Swift way of writing a button event handler. AnyObject is like the id object in Objective-C. We cast the sender into a UIButton and then get the title of the button which in this case, will be the text we want to enter in the text field.

To enter text using the keyboard, we use the textDocumentProxy object and call the insertText method.

The next step is to add a button to our Keyboard view. Add the two lines of code below to the viewDidLoad method. You can remove the automatically generated code in the viewDidLoad and textDidChange methods.

1
2
3
4
5
6
7
 override func viewDidLoad() {
        super.viewDidLoad()
 
        let button = createButtonWithTitle("A")
        self.view.addSubview(button)
 
    }

This adds a button with the title “A” into the keyboard input view. This will be our A key.

Now if you run the app and tap in the text field, you should see the A key in the keyboard. (You probably have to switch the keyboard, like we did the last time).

Tap the A button and see what happens… We’ve got text!

screen7

Okay, lets add some more keys and make this bad boy look like a real keyboard.

Let’s change the code we added to the viewDidLoad method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 override func viewDidLoad() {
        super.viewDidLoad()
 
     	  let buttonTitles = ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"]
        var buttons = UIButton[]()
        var keyboardRowView = UIView(frame: CGRectMake(0, 0, 320, 50))
 
        for buttonTitle in buttonTitles{
 
            let button = createButtonWithTitle(buttonTitle)
            buttons.append(button)
            keyboardRowView.addSubview(button)
        }
 
        self.view.addSubview(keyboardRowView)  
}

Now with this new piece of code, we have created and array of button titles and we create a list of buttons from these. Each button is now added to an array as well as a UIView which will be our first row of keys. This view is then added to the main keyboard view.

If you run this, you will probably only see the P key since all the buttons are in the same location. We need to add some constraints programmatically so they can be aligned in a row.

So we will create a new method to create the constraints

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
func addIndividualButtonConstraints(buttons: UIButton[], mainView: UIView){
 
        for (index, button) in enumerate(buttons) {
 
            var topConstraint = NSLayoutConstraint(item: button, attribute: .Top, relatedBy: .Equal, toItem: mainView, attribute: .Top, multiplier: 1.0, constant: 1)
 
            var bottomConstraint = NSLayoutConstraint(item: button, attribute: .Bottom, relatedBy: .Equal, toItem: mainView, attribute: .Bottom, multiplier: 1.0, constant: -1)
 
            var rightConstraint : NSLayoutConstraint!
 
            if index == buttons.count - 1 {
 
                rightConstraint = NSLayoutConstraint(item: button, attribute: .Right, relatedBy: .Equal, toItem: mainView, attribute: .Right, multiplier: 1.0, constant: -1)
 
            }else{
 
                let nextButton = buttons[index+1]
                rightConstraint = NSLayoutConstraint(item: button, attribute: .Right, relatedBy: .Equal, toItem: nextButton, attribute: .Left, multiplier: 1.0, constant: -1)
            }
 
 
            var leftConstraint : NSLayoutConstraint!
 
            if index == 0 {
 
                leftConstraint = NSLayoutConstraint(item: button, attribute: .Left, relatedBy: .Equal, toItem: mainView, attribute: .Left, multiplier: 1.0, constant: 1)
 
            }else{
 
                let prevtButton = buttons[index-1]
                leftConstraint = NSLayoutConstraint(item: button, attribute: .Left, relatedBy: .Equal, toItem: prevtButton, attribute: .Right, multiplier: 1.0, constant: 1)
 
                let firstButton = buttons[0]
                var widthConstraint = NSLayoutConstraint(item: firstButton, attribute: .Width, relatedBy: .Equal, toItem: button, attribute: .Width, multiplier: 1.0, constant: 0)
 
                mainView.addConstraint(widthConstraint)
            }
 
            mainView.addConstraints([topConstraint, bottomConstraint, rightConstraint, leftConstraint])
        }
    }

That is a lot of code, eh? With AutoLayout, you can’t really build up to it and you have to add all constraints at once or else it doesn’t work. The main work of the code above is to add a 1px constraint to the top and bottom of each key in relation to the view for the row. It also adds a 1px constraint to the left and right of each key in relation to the adjacent keys (or the row view if it is the first or last key in the row).

If you add the method call to the viewDidLoad function, we should be able to see the new row of keys show up.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    override func viewDidLoad() {
        super.viewDidLoad()
 
        let buttonTitles = ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"]
        var buttons = UIButton[]()
        var keyboardRowView = UIView(frame: CGRectMake(0, 0, 320, 50))
 
        for buttonTitle in buttonTitles{
 
            let button = createButtonWithTitle(buttonTitle)
            buttons.append(button)
            keyboardRowView.addSubview(button)
        }
 
        self.view.addSubview(keyboardRowView)
 
        addIndividualButtonConstraints(buttons, mainView: keyboardRowView)
}

screen4

Now, that’s looking more like a keyboard. The next step is to add the other row of keys. To do that, let’s do some quick refactoring. Create a new method that will implement each row of keys.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func createRowOfButtons(buttonTitles: NSString[]) -> UIView {
 
        var buttons = UIButton[]()
        var keyboardRowView = UIView(frame: CGRectMake(0, 0, 320, 50))
 
        for buttonTitle in buttonTitles{
 
            let button = createButtonWithTitle(buttonTitle)
            buttons.append(button)
            keyboardRowView.addSubview(button)
        }
 
        addIndividualButtonConstraints(buttons, mainView: keyboardRowView)
 
        return keyboardRowView
    }

We have basically extracted the viewDidLoad code into it’s own method. This new method takes in the array of titles for the row and returns the view that contains all the buttons for the row. Now we can call this bit of code for every row we want to add.

So our new vieDidLoad method will look like this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
override func viewDidLoad() {
        super.viewDidLoad()
 
        let buttonTitles1 = ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"]
        let buttonTitles2 = ["A", "S", "D", "F", "G", "H", "J", "K", "L"]
        let buttonTitles3 = ["CP", "Z", "X", "C", "V", "B", "N", "M", "BP"]
        let buttonTitles4 = ["CHG", "SPACE", "RETURN"]
 
        var row1 = createRowOfButtons(buttonTitles1)
        var row2 = createRowOfButtons(buttonTitles2)
        var row3 = createRowOfButtons(buttonTitles3)
        var row4 = createRowOfButtons(buttonTitles4)
 
        self.view.addSubview(row1)
        self.view.addSubview(row2)
        self.view.addSubview(row3)
        self.view.addSubview(row4)
 
    }

In the code above, we have added 4 rows of keys and then added these keys to a row which in turn is added to the main view.

We could run the code now, but you would only see the last row since they are all at the same location. We need to add some Autolayout constraints.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
func addConstraintsToInputView(inputView: UIView, rowViews: UIView[]){
 
        for (index, rowView) in enumerate(rowViews) {
            var rightSideConstraint = NSLayoutConstraint(item: rowView, attribute: .Right, relatedBy: .Equal, toItem: inputView, attribute: .Right, multiplier: 1.0, constant: -1)
 
            var leftConstraint = NSLayoutConstraint(item: rowView, attribute: .Left, relatedBy: .Equal, toItem: inputView, attribute: .Left, multiplier: 1.0, constant: 1)
 
            inputView.addConstraints([leftConstraint, rightSideConstraint])
 
            var topConstraint: NSLayoutConstraint
 
            if index == 0 {
                topConstraint = NSLayoutConstraint(item: rowView, attribute: .Top, relatedBy: .Equal, toItem: inputView, attribute: .Top, multiplier: 1.0, constant: 0)
 
            }else{
 
                let prevRow = rowViews[index-1]
                topConstraint = NSLayoutConstraint(item: rowView, attribute: .Top, relatedBy: .Equal, toItem: prevRow, attribute: .Bottom, multiplier: 1.0, constant: 0)
 
                let firstRow = rowViews[0]
                var heightConstraint = NSLayoutConstraint(item: firstRow, attribute: .Height, relatedBy: .Equal, toItem: rowView, attribute: .Height, multiplier: 1.0, constant: 0)
 
                inputView.addConstraint(heightConstraint)
            }
            inputView.addConstraint(topConstraint)
 
            var bottomConstraint: NSLayoutConstraint
 
            if index == rowViews.count - 1 {
                bottomConstraint = NSLayoutConstraint(item: rowView, attribute: .Bottom, relatedBy: .Equal, toItem: inputView, attribute: .Bottom, multiplier: 1.0, constant: 0)
 
            }else{
 
                let nextRow = rowViews[index+1]
                bottomConstraint = NSLayoutConstraint(item: rowView, attribute: .Bottom, relatedBy: .Equal, toItem: nextRow, attribute: .Top, multiplier: 1.0, constant: 0)
            }
 
            inputView.addConstraint(bottomConstraint)
        }
 
    }

This new method does a similar function to the last auto layout code we added. It adds a 1px constraint to the left and right of the row in relation to the main view and the adds a 0px constraint between the each row and the next one below and above it.

Now we need to call this bit of code from our viewDidLoad method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 override func viewDidLoad() {
        super.viewDidLoad()
 
        let buttonTitles1 = ["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"]
        let buttonTitles2 = ["A", "S", "D", "F", "G", "H", "J", "K", "L"]
        let buttonTitles3 = ["CP", "Z", "X", "C", "V", "B", "N", "M", "BP"]
        let buttonTitles4 = ["CHG", "SPACE", "RETURN"]
 
        var row1 = createRowOfButtons(buttonTitles1)
        var row2 = createRowOfButtons(buttonTitles2)
        var row3 = createRowOfButtons(buttonTitles3)
        var row4 = createRowOfButtons(buttonTitles4)
 
        self.view.addSubview(row1)
        self.view.addSubview(row2)
        self.view.addSubview(row3)
        self.view.addSubview(row4)
 
        row1.setTranslatesAutoresizingMaskIntoConstraints(false)
        row2.setTranslatesAutoresizingMaskIntoConstraints(false)
        row3.setTranslatesAutoresizingMaskIntoConstraints(false)
        row4.setTranslatesAutoresizingMaskIntoConstraints(false)
 
        addConstraintsToInputView(self.view, rowViews: [row1, row2, row3, row4])
    }

Here’s our new viewDidLoad method. You will see that we set the TranslatesAutoresizingMaskIntoConstraints on each row to false. This is to make sure our views use the auto layout methods and not springs and struts for the layout.

Now if you run the app, you will see out keyboard all nicely laid out. You can tap all the buttons to see them entered into the text field.

screen2

There’s a small problem though, the non-text keys are not functioning correctly. (for example, the backspace and space keys).

To fix that, we will need to change our didTapButton method to add the correct methods to call for these keys.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
    func didTapButton(sender: AnyObject?) {
 
        let button = sender as UIButton
        let title = button.titleForState(.Normal) as String
        var proxy = textDocumentProxy as UITextDocumentProxy
 
        proxy.insertText(title)
 
        switch title {
        case "BP" :
            proxy.deleteBackward()
        case "RETURN" :
            proxy.insertText("\n")
        case "SPACE" :
            proxy.insertText(" ")
        case "CHG" :
            self.advanceToNextInputMode()
        default :
            proxy.insertText(title)
        }
    }

We have included a switch statement which has a case statement for the title of the key. The backspace key calls the deleteBackward method on the proxy, the space key inserts a space and the CHG key changes the keyboard to either the system keyboard or the next keyboard installed.

What’s next?

We have come to the end of this tutorial on how to create a basic custom keyboard. Your homework is to take this further and see if you can add more advanced functionality, like using the Caps Lock to add uppercase letters, switching to a numeric/symbol keyboard scheme etc.

Download the project for the tutorial here.

103 comments

  1. Jonathan

    Hey Tope!
    Great tutorial for people starting out. I’ve made a couple of keyboards myself using Nibs for layouts and switching between them. Even though I’ve noticed a way longer delay when rendering my keyboard the first time than with Apple’s Keyboard. Do you know why this happens?

    • Rian

      In all likelihood they aren’t using buttons but a single tap area with a collision algorithm. UIButtons have unnecessary overhead you can optimize out by removing their interactive component.

    • Damian

      Hello,

      I have made an keyboard, but when I enable it under settings > keyboards, it doesn’t show up when I want to type something. I push the button to switch from keyboard, but it’s not in the list.

  2. Pingback: A Step-By-Step Tutorial On Using iOS 8′s New Keyboard Extension

  3. Sven

    Another swift-junky. Thank you for nothing. Just because its new doesnt mean its better. Swift is way slower than Obj-C. Stop following the hype.

  4. Pingback: Issue # 2 - September 5, 2014 | iOS Dev Newbie

  5. Pingback: Top iOS Development Resources For Two Weeks Ended September 14th, 2014

  6. Pingback: �?日一译:9月上旬iOS开�?�资�?汇总 | 闲散人生 | idlelife

      • Jeff

        I appreciate the tutorial, but the Sim log shows heaps and heaps of errors “Unable to simultaneously satisfy constraints.” There are 34 groups of errors, each with about a dozen constraints listed. Every button is listed. Heaps. I don’t know where to start.

      • Jeff

        I fixed the errors by settings two more priorities in addConstraintsToInputView: rightSideConstraint and bottomConstraint priority set to 800. Help from http://stackoverflow.com/a/23910943/236415

        • Drew Lustro

          Jeff,

          I’ve fixed all AutoLayout constraint warnings… perhaps with a different approach than your own. Tested on Xcode 6.1 stable.

          KeyboardViewController.swift
          https://gist.github.com/drewlustro/641d5844e43e87d0c011

  7. Emil

    BTW. Tip: Change the position of the social media share widget from left to right. As You see It’ just bad UI experience for your website. http://imgur.com/TmPjxvD

    • Drew Lustro

      +1 agreed. I was using Chrome Debugger to literally delete that DIV… just some padding-left in order, is all 😉

  8. Pingback: iOS8自定义输入法教程:如何创建第三方输入法 - 马开东�?�客

    • Tope

      Check out this link here
      https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/Keyboard.html

      There is a section that shows you how to change the height

  9. EarlyAdopterPro

    Thanks for the tutorial!

    Any ideas if the same approach can be used to create 3-d party iOS 8 keyboard? I want to make a keyboard for the language which is not supported in iOS and make it available for all iOS app (ass swype or swift keyboards)

    • Jaysoncopes

      Yes, of course it can. Use the same procedure as listed above (possibly a bit different- I’m going to have to try this myself to decide whether the constraints are properly defined) but make a layout in a different language’s keyboard and use the ACSII characters for that language. You may have to use some sort of importing for those characters, though.

  10. Preston

    Hey Tope, you know how we could make custom shapes for the keys, like in the picture you put up at the beginning of the post?

    • Tope

      Hi Preston, Sure.. please sign up to download the sample project and I will send you more details in a couple of days on how to make custom shapes

  11. Googler

    Hi Tope,

    Excellent tutorial, very clear.

    But getting crash on multiple time rotate keyboard like Portrait to Landscape and Landscape to Portrait.

    When I look in to debug console its giving me below error.

    “Unable to simultaneously satisfy constraints.”

    Constraints not satisfy.

    Please have a look, and if you got answer then please share with me.

  12. Chris Palian

    Hey thanks for this, it has helped a ton. Ive got it running really well but I have been trying to get the key that is pressed to change color while it is pressed.

    I tried adding this…

    let IMAGE1 = UIImage(named: “blue.png”)
    button.setBackgroundImage(IMAGE1, forState: UIControlState.Selected)

    into the func createButtonWithTitle(title: String) -> UIButton

    but have not been able to successfully change the background color, color or background image when a button is pressed.

    any suggestions?

  13. Anthony

    A keyboard like this will be rejected by Apple for this reason :

    Keyboard extensions must provide Number and Decimal keyboard types as described in the App Extension Programming Guide or they will be rejected

    How can we do this ?

    Thanks a lot !

  14. Preston

    How do we get the globe icon, the capitalize icon and the back space icons for our keyboards? Are they images apple put there or are they actual characters we can use?

  15. Pingback: 9月上旬iOS开�?�资�?汇总 - Cmgine

  16. Sezin Lynn

    how do I enable shifted keys? I’m doing for different language so shifted keyboard page have different characters.

  17. DEVON

    Hi there does anyone know how to do the popup keys like the iPhone keyboard and if you do please help me
    Thanks

  18. AppleNut

    Need help with: Keyboard extensions must provide Number and Decimal keyboard types as described in the App Extension Programming Guide or they will be rejected

    Making a keyboard of my own after reading this and i was rejected because i didn’t have this i don’t know how and i really need help big thanks to anyone who can help!!!

  19. Calhan

    Hello,
    why is it when choosing the keyboard always two names (app bundlename & Keyboard extension) is that not possible to change this?

  20. Pingback: iOS Library for easily creating fully customizable iOS 8 keyboards

  21. Pingback: iOS Library for easily creating fully customizable iOS 8 keyboards

  22. David

    Thanks for the tutorial!

    I’ve downloaded your keyboard and added caps, capslock, and a few other features. However, I can’t figure out how to change the shift key color when capslock is on. How do I reference the selected button object?

    I’ve got a few more questions, but let’s start simple and see if anyone responds…

    Thanks!

    — David

    code excerpt:

    func didTapButton(sender: AnyObject?) {

    let button = sender as UIButton
    var proxy = textDocumentProxy as UITextDocumentProxy

    if let title = button.titleForState(.Normal) {
    switch title {
    case “.” :
    capon = true
    proxy.insertText(“.”)
    spacelast = false
    capslast = false
    case “↑” :
    capon = !capon
    if capslock {
    capon = false
    capslock = false
    capslast = false
    }
    if capslast {
    capslock = true
    // THIS IS WHERE I WANT TO MAKE A COLOR CHANGE!
    }
    capslast = true
    case “�?” :
    proxy.deleteBackward()
    spacelast = false
    capslast = false
    case “RETURN” :
    proxy.insertText(“\n”)
    spacelast = false
    capslast = false
    case “SPACE” :
    if spacelast {
    proxy.deleteBackward()
    proxy.insertText(“. “)
    spacelast = false
    capon = true
    } else {
    proxy.insertText(” “)
    spacelast = true
    }
    capslast = false
    case “

    • TDH

      I was trying to use this to see if I could figure out how to add the colour change. The only issue is that now I can’t get your code to work with the rest of mine. It comes back with a list of “Use of unresolved identifier ‘(whatever)'”. Would you be able to help me fix this issue? Or if you have managed to get more than just the caps working, would you mind helping me learn how to improve the keyboard even further? Being new to code doesn’t help me out when trying to make a keyboard. Haha.

    • TDH

      So I’m an idiot and figured out what my issue was with the whole “…unresolved…”. My issue now is what I would do to make them actually do what they are meant to. Any suggestions?

      Again, sorry for constantly taking up more space on this page.

    • Amadeus

      Hi David,

      I tried to test out your code and somehow I got heaps of errors. Could you please elaborate on how you managed to get the caps lock feature to work? This seems to be driving me mad trying to figure it out on my own. Your help is greatly appreciated.

  23. Applerocks

    I need help adding a Number and Decimal Keyboard to my keyboard I made with this tutorial I was rejected by Apple because I didn’t have this please someone help i can’t figure out how to do it with a keyboard based off of this tutorial. Please help thanks to anyone that can!

    • Mark Thien

      it should be easy. just hide the existing and make:

      let buttonsNum1FirstRow = [“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”, “0”]
      let buttonsNum2FirstRow = [“-“, “/”, “:”, “;”, “(“, “)”, “”, “&”, “@”, “\””]
      let buttonsNum3FirstRow = [“#+=”, “.”, “,”, “?”, “!”, “‘”, “7”, “BP”]

      define rows as class variable instead of function variable

      var row1:UIView!
      var row2:UIView!
      var row3:UIView!
      var row4:UIView!
      var row1Num:UIView!

      Hide it like below:
      func didTapChangeToNumbersButton(sender: AnyObject?) {
      row1.hidden = true

      row1Num.hidden = false

      }

  24. Mark Thien

    Hi there,
    This is an excellent tutorial.
    I am adding a “123” button that will switch the keyboard to numeric input, just like iOS original keyboard like below:

    let buttonsNum1FirstRow = [“1”, “2”, “3”, “4”, “5”, “6”, “7”, “8”, “9”, “0”]
    let buttonsNum2FirstRow = [“-“, “/”, “:”, “;”, “(“, “)”, “”, “&”, “@”, “\””]
    let buttonsNum3FirstRow = [“#+=”, “.”, “,”, “?”, “!”, “‘”, “7”, “BP”]

    Hence I need to hide :

    let buttonsEnFirstRow = [“Q”, “W”, “E”, “R”, “T”, “Y”, “U”, “I”, “O”, “P”]
    let buttonsEnSecondRow = [“A”, “S”, “D”, “F”, “G”, “H”, “J”, “K”, “L”]
    let buttonsEnThirdRow = [“CP”, “Z”, “X”, “C”, “V”, “B”, “N”, “M”, “BP”]

    Should we approach the hide and unhide way or should create Xib files for each layout and switch between them?

    Cheers,
    Mark

    • Tope

      You can do it both ways.. but note that Apple wants your keyboard to load as quickly as possible so it most efficient way possible is better.

      • Mark Thien

        ok Thanks Tope. will test it out. but currently I just use simulator iOS 8 to test and it seems slow as when first time it takes like 3 seconds to load.

  25. Devon

    Tope I love your tutorials but can you show me how to make a keyboard that has pop up keys like the iPhone default keyboard
    I really hope you can
    Thanks

  26. KPatel

    Great tutorial,
    Would like to see some gesture recognizers perhaps. Also maybe some changing of layout based on landscape mode.

    Good start to making a keyboard tho

  27. Luke

    Hi,

    There are many alphanumeric keyboards out, but I don’t know of any numeric only keyboards. These are necessary for some apps, where only number input is required.

  28. Simon Anthony

    Hi, I developed the SiWriter chording keyboard app. To be able to create it as a replacement keyboard I need multi-touch facilities. Can this be easily added?

    Many thanks.

    Regards

  29. Robert

    I hope You don’t mind if I use the layout for my own keyboard that i will publish on the App Store I’ll put in my description credits for layout goes to appdesignvault

  30. TDH

    Am I the only one here that can’t get keyboards to load on the iPhone simulator after updating to Xcode 6.1 and OS X Yosemite? Is there any way to fix this if you have had this problem?

    • Drew Lustro

      You’re not the only one. I can get the keyboard to activate in the Contacts app on the Simulator, but unfortunately it always reverts to English + Emoji on my container app.

      • TDH

        Idk if this requires a developer’s license or not, but try using your phone (and maybe even quicktime on yosemite) to make a personal simulator of sorts.

  31. Drew Lustro

    I’ve fixed all AutoLayout constraint warnings. Tested on Xcode 6.1 stable.

    KeyboardViewController.swift
    https://gist.github.com/drewlustro/641d5844e43e87d0c011

  32. Drew Lustro

    Oh and I forgot to say, thank you for the excellent tutorial!

    I wasn’t expecting such a healthy lesson in programmatic AutoLayout constraints too. 😉

  33. TDH

    I forgot to say it last time, but thanks for the awesome tutorial. I am trying to become a full developer for iOS 8+ and this keyboard tutorial has really helped me learn so much. I plan on eventually placing my own keyboard onto the App Store. But I plan to eventually move away from the tutorial and make a very wide-spanning keyboard.

    While trying to expand I came across this issue (this was written by me on my laptop so I just lazily copied it over here):
    I’m trying to recreate the code for a “theme” that is found in the more in-depth code that you emailed, and I am getting this error saying “Use of undeclared type ‘KeyboardTheme'”. I have all of the code (at this point literally copied to try and see if that helped) from your files and it is still giving me this error. Anyone know a possible cause of this and/or how to fix it?

    • TDH

      So I managed to possibly figure out what happened:

      I may have originally made the two theme files “OS X Source” instead of “iOS Source”. I’m not 100% sure but I deleted both files and remade them from the ground up. It ended up building flawlessly this time. So it’s highly likely that this is all that happened.

      Sorry for wasting space on the page due to these two comments.

  34. TDH

    Sorry for commenting so many times in one day. I probably should have tried to work on everything at once before commenting each time.

    I am trying to add a number pad, lowercase, and autocorrect (which I think requires full access in settings) but have no real idea where to start. Is there any possible tutorials available that anyone here knows of (or even is creating on this site or outside) that can help me learn to do so.

    Thanks for any help and support!

  35. Amadeus

    Hi, I would like to thank you for this tutorial, it’s an excellent tutorial. I have a slight problem, I don’t know exactly how to enable the Caps function or Shift function. If anyone knows the line of code for this it would be greatly appreciated! Thanks.

  36. Jacob

    I am just geting in to the programing thing an it is really complicated for me. But in general I want to make as my first program a keyboard that locks and works exactly like the original keyboard but smaller to fit 6 Plus. Is there any one that have time to help me. Best regards Jacob

  37. Samy

    Hi Tope Thank you for the tutorial,
    You said that is your first project in swift, but are you going to start new projects in swift ? In particular applications like Localyze or other ?
    Thank you !

  38. Mary

    “Turn on the switch to enable it and accept the warning message.” There is no switch to enable it. I can’t get the keyboard to come up. I installed the keyboard but can’t test it. xcode 6.1

  39. Mary

    Requests OpenAccess Boolean under CustomKeyboard Supporting Files was set to NO. Setting it to YES gives the option for the permissions switch to enable the keyboard. Still not able to select the keyboard. It keeps showing the default.

    • Mary

      Ok so I found out the issue is a problem with xcode 6.1. The keyboard will show up in Spotlight. That was hours of frustration.

  40. gary benedik

    Check out Roxie’s Visual Keyboard. The options are insane - regardless of what you type.

  41. Sean

    Hi

    would the above code work for inserting Jpegs into the key spaces instead of letters?? if not does anyone here know where you could direct me to find that type of code? i am trying to make a keyboard for sending emoticons

    thanks
    Sean

  42. Tom

    Pretty good tutorial, but it’s really slow at startup. Anyway to speed up show up speed? I think the trouble is come from constraint, remove constraint, show up speed is really fast

  43. Ariel

    Great Tutorial Tope! I was wondering if you could share your knowledge on how to insert an image when tapping a button?

    Thanks!

  44. Pingback: iOS8自定义输入法教程:如何创建第三方输入法 | 网站采集

  45. Pingback: 9月上旬iOS开�?�资�?汇总 | 网站采集

  46. rulebreaker4

    First of all! Thanks a lot for this wonderful tutorial. I am new to swift (and IOS development) and don’t know much about properties of UIFramework. Can someone please explain how can i switch to the other rows ? I am making a Punjabi Keyboard and it works fine for all 4 rows, however i want to (for example) change to row6-row8 (with different letters) while the CP button is pressed. what should i type in the case statement for “CP”? can i Recall the addConstraintsToInputView and method on row6-row8 for same layout ? Any hint will be much appreciated. Thanks again!

  47. android apps

    Hi i am kavin, its my first occasion to commenting anyplace,
    when i read this paragraph i thought i could also create comment due to this brilliant paragraph.

  48. money online-

    My brother recommended I would possibly like this website.
    He was entirely right. This publish actually made my day.
    You can not believe simply how a lot time I
    had spent for this info! Thanks!

  49. Pingback: How To Make A Custom Keyboard Layout For Ios 5 | MY NEWS