Sunteți pe pagina 1din 45

Tell us what you think and win prizes in the Tuts+ Annual Survey 2014.

Dismiss

All Topics Find tutorials, courses, and more...

Code Categories Learning Guides

IOS 8

iOS 8: Creating a Custom


Keyboard in Swift
by Andrei Puni 24 Nov 2014
0 Comments

18 52 2

Starting with iOS 8, your applications can extend custom functionality and content
beyond your app, and make it available to users while they're using other apps or
the operating system. One way of extending the operating system is by creating a
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
custom keyboard.

In this tutorial I'm going to show you how to make your own custom keyboard using
Swift and the new app extension APIs. Before we do that, we are going to go over
what a keyboard extension can do, what it can't do, and what it should to get
approved for the App Store.

1. Overview
A custom keyboard replaces the system keyboard for users who want capabilities,
such as a novel text input method or the ability to enter text in a language not
otherwise supported by the operating system.

The essential function of a custom keyboard is simple, respond to taps, gestures, or


other input events, and provide text in the form of an unattributed NSString object
at the text insertion point of the current text input object.

After a user chooses a keyboard, it remains as the default one whenever they open
an app. For this reason the keyboard must allow the user to switch to another
keyboard.

There are two development essentials for every custom


open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
keyboard:

Trust. Your custom keyboard gives you access to what


a user types, so trust between you and your user is
essential.

A next keyboard key. The affordance that lets a user


switch to another keyboard is part of a keyboards user
interface; you must provide one in your keyboard. - App
Extension Programming Guide

If you only need to add a few buttons to the system keyboard, then you should look
into custom views for data input.

2. Requirements & Limitations

What a Custom Keyboard Can't Do


There are certain text input objects that your custom keyboard is not eligible to type
into. These include secure text fields for entering passwords and phone pad
objects, such as the phone number fields in the Contacts application.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Your custom keyboard does not have access to the view hierarchy of the input, it
cannot control the cursor, and is unable to select text. Also, the custom keyboard
cannot display anything above the top row. The system keyboard isn't limited by
these constraints. For example, it shows an extension when you tap a key to show
the user what key was tapped.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
The red line shows the top limit of a custom keyboard.

Sandboxing
By default, a keyboard has no network access and cannot share files with its
containing app. To enable these capabilities, set the value of
the RequestsOpenAccess key in the Info.plist file to YES . Doing so expands the
keyboard's sandbox as described in Apple's App Extension Programming Guide.

If you do request open access, your keyboard gains the following capabilities, each
with a concomitant responsibility:

access to location services and the address book database, each requiring
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
the user's permission on first access
option to use a shared container with the keyboard's containing app, which
enables features, such as providing a custom lexicon management user
interface in the containing app
ability to send keystrokes and other input events for server-side processing
access to iCloud, which you can use, for example, to ensure that keyboard
settings and your custom autocorrect lexicon are up to date on all devices
owned by the user
access to Game Center and in-app purchase through the containing app
ability to work with managed apps if you design your keyboard to support
mobile device management (MDM)

Be sure to read Apple's Designing for User Trust document, which describes your
responsibilities for respecting and protecting user data in case you request open
access.

3. How It Works
In the most basic form we have an application that contains a keyboard extension
and a UIInputViewController that controls the keyboard and responds to user
events.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
The Custom Keyboard template contains a subclass of UIInputViewController,
which is the primary view controller of your keyboard. Let's look at the interface to
get a feel of how it works.

01 class UIInputViewController : UIViewController, UITextInputDelegate, NSObjectProto


02
03 var inputView: UIInputView!
04
05 var textDocumentProxy: NSObject! { get }
06
07 func dismissKeyboard()
08 func advanceToNextInputMode()
09
10 // This will not provide a complete repository of a language's vocabulary.
11 // It is solely intended to supplement existing lexicons.
12 func requestSupplementaryLexiconWithCompletion(completionHandler: ((UILexicon!
13 }

inputView is the view used for the keyboard, it is the same as


the view property
dismissKeyboard method can be called to dismiss the keyboard
advanceToNextInputMode is used to change between keyboards
textDocumentProxy is the object that you'll use to interact with the current
text input

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
1 self.textDocumentProxy.insertText(
"Tuts+") // inserts the string "Tuts+" at the inser
2
3 self.textDocumentProxy.deleteBackward()
// Deletes the character to the left of the i

UIInputViewController conforms to the UITextInputDelegate protocol,


notifying you when the text or text selection changes through the
the selectionWillChange, selectionDidChange, textWillChange and textDidChangeevents

4. Making a Calculator Keyboard


Let's create a custom keyboard to make all this a little bit more tangible. We'll make
a simple keyboard that can handle numeric input and simple operations. We're
going to use a XIB file for the keyboard's user interface.

Step 1: Create a New Project


Open Xcode 6, create a newSingle View Application and select Swift as the
programming language. Name it CalculatorKeyboard.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Step 2: Add a Text Field
Open Main.storyboard and drag a text field from the Objects Library. We'll use
this to test the keyboard later. Center the text field and add the necessary layout
constraints as shown below.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
If you call textField.becomeFirstResponder()in viewDidLoad the keyboard will
open when you start the app.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Step 3: Add the Keyboard Extension
Select the project file in theProject Navigator and add a new target by clicking the
plus button at the bottom.

Select Application Extension on the left, choose the Custom Keyboard template,
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
and name it Calculator.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
This will create a new group namedCalculator, containing two
files KeyboardViewController.swift and Info.plist.

Step 4: Cleaning Up
Open KeyboardViewController.swift. The template keyboard has one button,
letting the user switch between keyboards. Remove the code in

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
the viewDidLoad method.

Step 5: Creating the User Interface


Right click the Calculator group and select New File.... Select the User
Interface section on the left, choose the View template, and name it Calculator.
This should create a file named Calculator.xib.

Open the XIB file and, in the Attributes Inspector on the right, set the size
to Freeform and the status bar to None.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
In the Size Inspector set the width of the view to 320 and the height to 160 .

Drag a button from the Objects Library to the view. In the Attributes Inspector,
set the title to 1. In the Size Inspector, set the button's width and height to
30 . Move the button to the top right corner of the view until it aligns with the
margins.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Copy the button by clicking and dragging the button while pressing theOption key.
Position the second button below the first one.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Select the buttons by pressing Command-A and copy the buttons. Position the new
buttons below the first and second button.

Repeat the process to create another column of buttons until you have four columns
of buttons.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Next, select the column on the left and make a copy that aligns with the left border
of the view.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Set the width of the buttons to 140 points. Replace the top left button with a label
that has the same size as the button. Rename the buttons like in the screenshot
bellow.

Give the view a blueish background color and set the background color for the
buttons to white with an opacity of 15%. And for the display label, make it black with
an opacity of 15%. Set the text size to 18 points for every user interface object and
set the text color to white. The user interface should now look like this:

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Step 6: Loading the User Interface
We first need to create a property in which to store the user interface.

1 class KeyboardViewController: UIInputViewController {


2 var calculatorView: UIView!
3
4 ...
5 }

Create a method named loadInterface and call it in the viewDidLoad method of


the KeyboardViewController.

01 class KeyboardViewController: UIInputViewController {

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
01 class KeyboardViewController: UIInputViewController {
02 ...
03
04 override func viewDidLoad() {
05 super.viewDidLoad()
06
07 loadInterface()
08 }
09
10 func loadInterface() {
11 // load the nib file
12 var calculatorNib = UINib(nibName:"Calculator", bundle: nil)
13 // instantiate the view
14 calculatorView = calculatorNib.instantiateWithOwner(self, options: nil)[0]
15
16 // add the interface to the main view
17 view.addSubview(calculatorView)
18
19 // copy the background color
20 view.backgroundColor = calculatorView.backgroundColor
21 }
22
23 ...
24 }

Step 7: Testing the Keyboard


At this point you should be able to test your new keyboard. With the
CalculatorKeyboard scheme selected, build and run the application on your
device. This will add a new keyboard to your device. However, before you can use
it you first need to install it.
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Go to Settings > General > Keyboard > Keyboards and select Add new
Keyboard. There you'll find the Calculator keyboard in the list of third-party
keyboards. Select and install the keyboard. The next time you open the keyboard
you should be able to see your new keyboard by pressing the next keyboard button.

If you are using the iOS Simulator, the custom keyboard might not work inside your
app. To see the keyboard press home and open Spotlight.

Step 8: Next Keyboard


Create a property for the next keyboard button in
the KeyboardViewController class.

1 class KeyboardViewController: UIInputViewController {


2
3 @IBOutlet var nextKeyboardButton: UIButton!
4
5 ...
6 }

Open Calculator.xib , Select File's Owner, and in the Identity Inspector change
its class to KeyboardViewController.

Right click on the Next Keyboard button and connect a referencing outlet to
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
the File's Owner.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
In the loadInterface method, we add an action to the nextKeyboard button as
shown below.

01 class KeyboardViewController: UIInputViewController {


02 ...
03
04 func loadInterface() {
05 ...
06
07 // This will make the button call advanceToNextInputMode() when tapped
08 nextKeyboardButton.addTarget(self, action:
"advanceToNextInputMode"
09 }
10
11 }

Step 9: Number Display


Create a property for the display and connect the referencing outlet in Interface
Builder.

1 class KeyboardViewController: UIInputViewController {


2
3 @IBOutlet var display: UILabel!
4
5 ...
6 }

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Create a method named clearDisplay and call it in the viewDidLoad method,
after invoking loadInterface. The display should now show 0 when you open the
keyboard.

01 class KeyboardViewController: UIInputViewController {


02 ...
03
04 override func viewDidLoad() {
05 super.viewDidLoad()
06
07 loadInterface()
08 clearDisplay()
09 }
10
11 ...
12
13 @IBAction func clearDisplay() {
14 display.text = "0"
15 }
16 }

Connect the C button's touch up inside event to the clearDisplay method in


Interface Builder.

Step 10: Number Input


Time to handle numeric input. When you open the keyboard it shows0 on the
display. If you tap a number key, it should replace the display to that number.
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Create a property named shouldClearDisplayBeforeInsertingto implement this
behavior.

Create a method named didTapNumber and connect it in Interface Builder to all the
number buttons for the touch up inside event. The method uses the titleLabel
of the button to determine which number was tapped.

01 class KeyboardViewController: UIInputViewController {


02 var shouldClearDisplayBeforeInserting =true
03
04 ...
05
06 @IBAction func didTapNumber(number: UIButton) {
07 if shouldClearDisplayBeforeInserting {
08 display.text = ""
09 shouldClearDisplayBeforeInserting =false
10 }
11
12 if var numberAsString = number.titleLabel?.text {
13 var numberAsNSString = numberAsString as NSString
14 if var oldDisplay = display?.text! {
15 display.text = "\(oldDisplay)\(numberAsNSString.intValue)"
16 } else {
17 display.text = "\(numberAsNSString.intValue)"
18 }
19 }
20 }
21 }

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Update the clearDisplay method as shown below.

1 class KeyboardViewController: UIInputViewController {


2 ...
3
4 @IBAction func clearDisplay() {
5 display.text = "0"
6 shouldClearDisplayBeforeInserting =true
7 }
8 }

The keyboard code is in a different target than your app. Because of this the debug
logs aren't visible. To see the logs for the Calculator target, open the system log
from the iOS Simulator.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Step 11: Dot Input
The button to insert a dot should add a dot to the display, but only if there isn't a dot
present yet.

01 class KeyboardViewController: UIInputViewController {


02 ...
03
04 @IBAction func didTapDot() {
05 if let input = display?.text {
06 var hasDot = false
07 for ch in input.unicodeScalars {
08 if ch == "." {
09 hasDot = true
10 break
11 }
12 }
13 if hasDot == false {
14 display.text = "\(input)."
15 }
16 }
17 }
18 }

Step 12: Inserting Text


The button to insert text should add the calculator display text to the insertion point.
To do this, we use the textDocumentProxy property as shown below.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
01 class KeyboardViewController: UIInputViewController {
02 ...
03
04 @IBAction func didTapInsert() {
05 var proxy = textDocumentProxy as UITextDocumentProxy
06
07 if let input = display?.text as String? {
08 proxy.insertText(input)
09 }
10 }
11 }

Step 13: Handling Operations


Because we're implementing a simple keyboard that doesn't supportexpression
trees, 1 + 2 * 3 will equal 9 . We're going to use a simpler model in which the
calculator has an internal memory slot on which it can apply operations.

Let's take a simple input in order to understand how the calculator algorithm works:

user taps 1 , the display should change from 0 to 1


user taps + , the calculator should remember to add the next inputted number
to 1
user taps 2 , the display should change from 1 to 2
user taps * , the display and the internal memory of the calculator should
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
change to 3 , the calculator should remember to multiply the internal memory
with the next inputted number
user taps 3 , the display should remain 3
user taps = , the calculator should apply the last operation and the display
should change to 9

Observations:

the calculator should remember the next operation to apply


after inputting a number if an operation or equal is pressed, the calculator
should apply the last remembered operation
if the user presses two or more operations without inputting a number, the
calculator should remember the last one
after an operation is applied, the display should update with the result
after a result is displayed, the display should clear before writing another
number

In order to implement the calculator, we are going to need:

an internalMemory property that stores the temporary result


a property that stores the nextOperation
another one that to remember if it should apply the nextOperation after an
operation is pressed
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
01 enum Operation {
02 case Addition
03 case Multiplication
04 case Subtraction
05 case Division
06 case None
07 }
08
09 class KeyboardViewController: UIInputViewController {
10 var internalMemory = 0.0
11 var nextOperation = Operation.None
12 var shouldCompute = false
13
14 ...
15 }

Create a method named didTapOperation and connect it to the operation buttons


touch up inside event in Interface Builder. The method will use the button title to
determine which operation was pressed.

01 class KeyboardViewController: UIInputViewController {


02 ...
03
04 @IBAction func didTapOperation(operation: UIButton) {
05 if shouldCompute {
06 computeLastOperation()
07 }
08
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
08
09 if var op = operation.titleLabel?.text {
10 switch op {
11 case "+":
12 nextOperation = Operation.Addition
13 case "-":
14 nextOperation = Operation.Subtraction
15 case "X":
16 nextOperation = Operation.Multiplication
17 case "%":
18 nextOperation = Operation.Division
19 default:
20 nextOperation = Operation.None
21 }
22 }
23 }
24 }

Create and implement the computeLastOperation method.

01 class KeyboardViewController: UIInputViewController {


02 ...
03
04 @IBAction func computeLastOperation() {
05 // remember not to compute if another operation is pressed without inputin
06 shouldCompute = false
07
08 if var input = display?.text {
09 var inputAsDouble = (input as NSString).doubleValue
10 var result = 0.0
11

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
11
12 // apply the operation
13 switch nextOperation {
14 case .Addition:
15 result = internalMemory + inputAsDouble
16 case .Subtraction:
17 result = internalMemory - inputAsDouble
18 case .Multiplication:
19 result = internalMemory * inputAsDouble
20 case .Division:
21 result = internalMemory / inputAsDouble
22 default:
23 result = 0.0
24 }
25
26 nextOperation = Operation.None
27
28 var output = "\(result)"
29
30 // if the result is an integer don't show the decimal point
31 if output.hasSuffix(".0") {
32 output = "\(Int(result))"
33 }
34
35 // truncatingg to last five digits
36 var components = output.componentsSeparatedByString(
".")
37 if components.count >= 2 {
38 var beforePoint = components[0]
39 var afterPoint = components[1]
40 if afterPoint.lengthOfBytesUsingEncoding(NSUTF8StringEncoding) > 5
41 let index: String.Index = advance(afterPoint.startIndex, 5)
42 afterPoint = afterPoint.substringToIndex(index)
43 }

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
43 }
44 output = beforePoint +"." + afterPoint
45 }
46
47
48 // update the display
49 display.text = output
50
51 // save the result
52 internalMemory = result
53
54 // remember to clear the display before inserting a new number
55 shouldClearDisplayBeforeInserting =true
56 }
57 }
58 }

Update the clearDisplayMethod as shown below. When the user starts to write the
first number, the internal memory should be set to 0 and nextOperation should
be addition. That way, after the user inputs the first number and presses an
operation, the calculator will remember the inputted number.

01 class KeyboardViewController: UIInputViewController {


02 ...
03
04 @IBAction func clearDisplay() {
05 display.text = "0"
06 internalMemory = 0
07 nextOperation = Operation.Addition
08 shouldClearDisplayBeforeInserting =true
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
08 shouldClearDisplayBeforeInserting =true
09 }
10 }

Advertisement

Step 14: Finishing Touches


Let's use the IBInspectable declaration attribute to add a corner radius to the
buttons and display. First, create a subclass of UIButton and UILabel .

01 class RoundButton: UIButton {


02 @IBInspectable var cornerRadius: CGFloat = 0 {
03 didSet {

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
03 didSet {
04 layer.cornerRadius = cornerRadius
05 }
06 }
07 }
08
09 class RoundLabel: UILabel {
10 @IBInspectable var cornerRadius: CGFloat = 0 {
11 didSet {
12 layer.cornerRadius = cornerRadius
13 }
14 }
15 }

In Interface Builder, select the buttons and change their class to RoundButton in the
Identity Inspector. In the Attributes inspector, you should see the new corner
radius attribute.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Do the same for the display label. Your keyboard should now look like this.

Conclusion
You should now be able to make a custom keyboard in iOS using the app extension
APIs. Remember that every custom keyboard must have a way to switch to the next
keyboard and that your keyboard cannot connect to the internet, access location
services, or talk with its containing app by default, but you can request these
capabilities.

The system will use the default keyboard for secure fields, such as password and
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
phone number fields. Don't forget that the code for the custom keyboard lives in a
separate target. Because of this the debug logs aren't visible. To see them, open
the system log from the iOS Simulator.

Advertisement

Difficulty: Suggested Tuts+ Course


Intermediate
Length:
Medium
Categories:

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
iOS 8 Swift iOS SDK Xcode 6 Xcode

IDEs Mobile Development

Translations Available:

Tuts+ tutorials are translated by our community Building iOS Apps in C# With Xamarin Start
members. If you'd like to translate this post into
another language, let us know!

Related Tutorials

About Andrei Puni Create A Custom Keyboard on


Android
Andrei started programming when he was
Code
10, after training for four years he won a
bronze medal at the International
Olympiad in Informatics in 2009. In the last 5 years
Create a Text to Speech App With
he has worked as an iOS developer for local
Swift
companies and as a freelancer.
Code

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
iOS 8: Creating a Today Widget
Code

Jobs

WordPress Developer
at WebDevStudios in Los Angeles, CA,
USA

Advertisement
Front-End WordPress Designer
at WebDevStudios in Los Angeles, CA,
USA

Envato Market Item

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
0 Comments Tuts+ Hub

Sort by Best

Start the discussion

Be the first to comment.

Subscribe d Add Disqus to your site Privacy

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Advertisement

18,722 Tutorials 447 Video Courses


Teaching skills to millions worldwide.

Follow Us Email Newsletters

Get Tuts+ updates, news, surveys &



offers.

Email Address
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
Help and Support Email Address

FAQ
Subscribe
Terms of Use
Contact Support Privacy Policy
About Tuts+
Advertise
Teach at Tuts+

Custom digital services like logo design, WordPress installation, video


production and more.
Check out Envato Studio

Add more features to your website such as user profiles, payment


gateways, image galleries and more.
Browse WordPress Plugins

2014 Envato Pty Ltd. Trademarks and brands are the property of their respective
open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com
owners.

open in browser PRO version Are you a developer? Try out the HTML to PDF API pdfcrowd.com

S-ar putea să vă placă și