Swiftでカスタムキーボードを作ってみた

# 概要
iOS8のカスタムキーボード関連の記事は色々ありますので、
カスタムキーボードを作成するまでの手順は軽く書いて、
カスタムキーボードを作る上でハマった点についても書いていこうと思います。
※Mac歴＆iOS系プログラミング歴は短いので普通のことで良くハマります。

ハマった点は以下の通り

* ハマった点①: 角丸ボタンはどうやって作るの？
* ハマった点②: 自作キーボードはどうやって反映するの？
* ハマった点③: さっきは自作キーボードが表示されたのに...<font color="#ff0000">(一番ハマった)</font>

# 開発環境

* OS X Mavericks
* Xcode 6.0.1
* iOS Simulator

# 開発の流れ

## ダミーのProject作成

カスタムキーボード単体プロジェクトは無いようで...
ダミーの Single View Application プロジェクトの上にカスタムキーボードを作成する必要があるようです。

1. Xcode -> File -> New -> Project...
2. iOS -> Application -> Single View Application

Project から Single View Application を選んで...
![スクリーンショット 2014-10-14 8.08.54.png](https://qiita-image-store.s3.amazonaws.com/0/53393/e345ba95-f100-0969-fd71-fc78a94ee8eb.png)

適当にプロジェクトの設定をする。
![スクリーンショット 2014-10-14 8.09.20.png](https://qiita-image-store.s3.amazonaws.com/0/53393/621c5d26-4fdf-7076-7324-5c4f68943290.png)

## カスタムキーボードのTarget作成

1. Xcode -> File -> New -> Target...
2. iOS -> Application -> Custom Keyboard

Target から Custom Keyboard を選んで...
![スクリーンショット 2014-10-14 8.09.41.png](https://qiita-image-store.s3.amazonaws.com/0/53393/dc3cdf70-ce3a-c8c5-09b9-00042640d15f.png)

適当にターゲットの設定をする。
このとき Project やら Embed in Application が、
ダミーの Single View Application を指していることを確認。
![スクリーンショット 2014-10-14 8.10.38.png](https://qiita-image-store.s3.amazonaws.com/0/53393/f3af9f67-bc88-4a00-4ec5-acabde0c2046.png)

作成したらこんな感じのプロジェクト構成になった。
![スクリーンショット 2014-10-14 8.12.46.png](https://qiita-image-store.s3.amazonaws.com/0/53393/cb793830-024a-d2f7-9259-12c8351b9544.png)

## Xibファイルの作成

1. Xcode -> File -> New -> File...
2. iOS -> User Interface -> View

いつも通り適当に。
KeyboardView.xib という名前にしておきます。(後でプログラム上で使います)
![スクリーンショット 2014-10-15 11.39.00.png](https://qiita-image-store.s3.amazonaws.com/0/53393/01b8be95-cfaa-4133-2af1-d9c610ee6a49.png)

## Xibファイルにボタンを配置

![スクリーンショット 2014-10-15 5.07.30.png](https://qiita-image-store.s3.amazonaws.com/0/53393/c4114b44-6dce-3698-f214-e50bf55a4252.png)

### ハマった点①: 角丸ボタンはどうやって作るの？

ここは別にやらなくても良かった。
ただ、やりたかっただけ。

ソース上では、以下のようにやるらしいが...
ボタンの Property を作成しないといけないのかな？

```swift:Viewを角丸にする
[[view layer] setCornerRadius:10.0];
[view setClipsToBounds:YES];
```

とかとか色々調べていたら、xib上からもできた。
**User Defined Runtime Attribute**のところに**layer.cornerRadius**を追加する。
**Value**は数値が大きいほど、丸くなる範囲が大きくなる。

![20141014215127.png](https://qiita-image-store.s3.amazonaws.com/0/53393/7476dc0e-042e-d76e-4c0a-be13a84b8f56.png)

ちなみに、この設定をしてもプレビューには反映しない。
実行時にのみ反映するっぽい。

## UIとソースを紐付ける

Ctrlキーとか使って、Buttonとソースを紐付けた。
元々書かれていたデフォルトソースはほとんど消した。

```swift:Keyboardソース
class KeyboardViewController: UIInputViewController {

    @IBOutlet var nextKeyboardButton: UIButton!

    override func updateViewConstraints() {
        super.updateViewConstraints()
    
        // Add custom view sizing constraints here
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        var v = UINib(nibName:"KeyboardView", bundle:nil).instantiateWithOwner(self,options:nil)[0] as UIView
        self.inputView.addSubview(v)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated
    }

    override func textWillChange(textInput: UITextInput) {
        // The app is about to change the document's contents. Perform any preparation here.
    }

    override func textDidChange(textInput: UITextInput) {
        // The app has just changed the document's contents, the document context has been updated.
    }

    @IBAction func buttonNext(sender: AnyObject) {
        self.advanceToNextInputMode()
    }
    
    @IBAction func button1(sender: AnyObject) {
        var proxy = textDocumentProxy as UITextDocumentProxy
        proxy.insertText("Button1")
    }
    
    @IBAction func button2(sender: AnyObject) {
        var proxy = textDocumentProxy as UITextDocumentProxy
        proxy.insertText("Button2")
    }
    
    @IBAction func button3(sender: AnyObject) {
        var proxy = textDocumentProxy as UITextDocumentProxy
        proxy.insertText("Button3")
    }
    
    @IBAction func button4(sender: AnyObject) {
        var proxy = textDocumentProxy as UITextDocumentProxy
        proxy.insertText("Button4")
    }
    
    @IBAction func button5(sender: AnyObject) {
        var proxy = textDocumentProxy as UITextDocumentProxy
        proxy.insertText("Button5")
    }
   
    @IBAction func button6(sender: AnyObject) {
        var proxy = textDocumentProxy as UITextDocumentProxy
        proxy.insertText("Button6")
    }
}
```

## iOSシミュレーターで実行する

### ハマった点②: 自作キーボードはどうやって反映するの？

適当なテキストボックスに合わせてもデフォルトキーボード以外が表示されなかったので困った。
そりゃキーボードを追加していないもの...出ないわな...

Command + Shift + H でシミュレーターのホームに戻る。

Settings -> General -> Keyboard -> Keyboards -> Add New Keyboard... で自作キーボードを追加する。

これでキーボードを入れ替えていけば自作キーボードが表示される。

実行した結果はこんな感じ。

![iOS Simulator Screen Shot 2014.10.15 5.07.52.png](https://qiita-image-store.s3.amazonaws.com/0/53393/bcb27e43-159f-4ec2-3f2a-766a25f40f0d.png)

### ハマった点③: さっきは自作キーボードが表示されたのに...<font color="#ff0000">(一番ハマった)</font>

急にキーボードが一切出なくなった。

再インストールしても出ない。
シミュレーター側を1回リセットしても出ない。

色々調べていると原因はハードウェアキーボードらしい。
テキストボックスにはPCのキーボードからも入力できるのが問題らしい。

解決方法は、

iOS Simulator -> Hardware -> Keyboard -> Connect Hardware Keyboard のチェックを外す。

# その他

Swiftは文末のセミコロンはあっても無くても良い。

いつもポインタと仲良くしている私としては、
セミコロン忘れで怒られないのがちょっと寂しい。