質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

1回答

2059閲覧

カスタムキーボード作成中に遭遇したUIButtonがnilで実行時エラー

sacakoro

総合スコア35

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/06/06 23:36

前提・実現したいこと

Swiftでオリジナルのキーボードを作成しようとしています。
こちらのサンプルプログラムをダウンロードし、Objective-Cで書かれていたのでSwiftに書き換えて改造しようとしました。
https://github.com/bjhstudios/iOSCustomKeyboard

発生している問題・エラーメッセージ

viewDidLoad関数から呼び出されたinitializeKeyboard関数の中のself.spaceButton.addGestureRecognizer(spaceDoubleTap)の部分において

Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

が発生します。

該当のソースコード

Swift

1// 2// KeyboardViewController.swift 3// keyboard 4// 5// Created by KAZUSHIGE SATO on 2018/06/06. 6// Copyright © 2018年 KAZUSHIGE SATO. All rights reserved. 7// 8 9import UIKit 10 11class KeyboardViewController: UIInputViewController { 12 13 var _shiftStatus : Int = 0 //0 = off, 1 = on, 2 = caps lock 14 15 //keyboard rows 16 @IBOutlet weak var numbersRow1View: UIView! 17 @IBOutlet weak var numbersRow2View: UIView! 18 @IBOutlet weak var symbolsRow1View: UIView! 19 @IBOutlet weak var symbolsRow2View: UIView! 20 @IBOutlet weak var numbersSymbolsRow3View: UIView! 21 22 //keys 23 // これはどうやって書き換えるのか? 24//@property (nonatomic, strong) IBOutletCollection(UIButton) NSArray *letterButtonsArray; 25 @IBOutlet weak var letterButtonsArray: NSArray! 26 @IBOutlet weak var switchModeRow3Button: UIButton! 27 @IBOutlet weak var switchModeRow4Button: UIButton! 28 @IBOutlet weak var shiftButton: UIButton! 29 @IBOutlet weak var spaceButton: UIButton! 30 31 override func updateViewConstraints() { 32 super.updateViewConstraints() 33 34 // Add custom view sizing constraints here 35 } 36 37 override func viewDidLoad() { 38 super.viewDidLoad() 39 40 DispatchQueue.main.async { 41 self.initializeKeyboard() 42 } 43 } 44 45 override func viewWillLayoutSubviews() { 46 super.viewWillLayoutSubviews() 47 48 } 49 50 func initializeKeyboard() { 51 //start with shift on 52 _shiftStatus = 1 53 //initialize space key double tap 54 let spaceDoubleTap = UITapGestureRecognizer(target: self, action: #selector(spaceKeyDoubleTapped)) 55 spaceDoubleTap.numberOfTapsRequired = 2 56 spaceDoubleTap.delaysTouchesEnded = false 57 self.spaceButton.addGestureRecognizer(spaceDoubleTap) 58 59 //initialize shift key double and triple tap 60 let shiftDoubleTap = UITapGestureRecognizer.init(target: self, action: #selector(shiftKeyDoubleTapped)) 61 let shiftTripleTap = UITapGestureRecognizer.init(target: self, action: #selector(shiftKeyPressed)) 62 63 shiftDoubleTap.numberOfTapsRequired = 2 64 shiftTripleTap.numberOfTapsRequired = 3 65 66 shiftDoubleTap.delaysTouchesEnded = false 67 shiftTripleTap.delaysTouchesEnded = false 68 69 self.shiftButton.addGestureRecognizer(shiftDoubleTap) 70 self.shiftButton.addGestureRecognizer(shiftTripleTap) 71 } 72 73 override func didReceiveMemoryWarning() { 74 super.didReceiveMemoryWarning() 75 // Dispose of any resources that can be recreated 76 } 77 78 override func textWillChange(_ textInput: UITextInput?) { 79 // The app is about to change the document's contents. Perform any preparation here. 80 } 81 82 override func textDidChange(_ textInput: UITextInput?) { 83 // The app has just changed the document's contents, the document context has been updated. 84 85 86 } 87 @IBAction func globeKeyPressed(sender: Any) { 88 //required functionality, switches to user's next keyboard 89 self.advanceToNextInputMode() 90 } 91 @IBAction func keyPressed(sender: UIButton) { 92 //inserts the pressed character into the text document 93 self.textDocumentProxy.insertText((sender.titleLabel?.text!)!) 94 95 //if shiftStatus is 1, reset it to 0 by pressing the shift key 96 if (_shiftStatus == 1) { 97 self.shiftKeyPressed(self.shiftButton) 98 } 99 } 100 @IBAction func backspaceKeyPressed(sender: UIButton) { 101 102 self.textDocumentProxy.deleteBackward() 103 104 } 105 @IBAction func spaceKeyPressed(_ sender: Any) { 106 self.textDocumentProxy.insertText(" ") 107 } 108 /* 109 func spaceKeyDoubleTapped(sender: UIButton) { 110 //double tapping the space key automatically inserts a period and a space 111 //if necessary, activate the shift button 112 self.textDocumentProxy.deleteBackward() 113 self.textDocumentProxy.insertText(". ") 114 115 if (_shiftStatus == 0) { 116 self.shiftKeyPressed(self.shiftButton) 117 } 118 } 119 */ 120 @IBAction func returnKeyPressed(sender: UIButton) { 121 self.textDocumentProxy.insertText("\n") 122 } 123 124 @objc func shiftKeyDoubleTapped(_ sender: UIButton) { 125 _shiftStatus = 2 126 127 self.shiftKeys() 128 } 129 @IBAction func shiftKeyPressed(_ sender: UIButton) { 130 //if shift is on or in caps lock mode, turn it off. Otherwise, turn it on 131 _shiftStatus = _shiftStatus > 0 ? 0 : 1; 132 133 self.shiftKeys() 134 } 135 func shiftKeys() { 136 137 //if shift is off, set letters to lowercase, otherwise set them to uppercase 138 if (_shiftStatus == 0) { 139 for letterButton in self.letterButtonsArray { 140 (letterButton as! UIButton).setTitle((letterButton as! UIButton).titleLabel?.text?.lowercased(), for:UIControlState.normal) 141 } 142 } else { 143 for letterButton in self.letterButtonsArray { 144 (letterButton as! UIButton).setTitle((letterButton as! UIButton).titleLabel?.text?.uppercased(), for:UIControlState.normal) 145 } 146 } 147 148 //adjust the shift button images to match shift mode 149 let shiftButtonImageName = String.init(format:"shift_%i.png", arguments: [_shiftStatus]) 150 self.shiftButton.setImage(UIImage(named: shiftButtonImageName), for:UIControlState.normal) 151 152 let shiftButtonHLImageName = String.init(format:"shift_%iHL.png", arguments: [_shiftStatus]) 153 self.shiftButton.setImage(UIImage(named: shiftButtonHLImageName), for:UIControlState.highlighted) 154 155 } 156 157 @objc func spaceKeyDoubleTapped(_ sender: UIButton) { 158 159 //double tapping the space key automatically inserts a period and a space 160 //if necessary, activate the shift button 161 self.textDocumentProxy.deleteBackward() 162 self.textDocumentProxy.insertText(". ") 163 164 if (_shiftStatus == 0) { 165 self.shiftKeyPressed(self.shiftButton) 166 } 167 168 } 169 170 @IBAction func switchKeyboardMode(sender :UIButton) { 171 172 self.numbersRow1View.isHidden = true 173 self.numbersRow2View.isHidden = true 174 self.symbolsRow1View.isHidden = true 175 self.symbolsRow2View.isHidden = true 176 self.numbersSymbolsRow3View.isHidden = true 177 178 //switches keyboard to ABC, 123, or #+= mode 179 //case 1 = 123 mode, case 2 = #+= mode 180 //default case = ABC mode 181 182 switch (sender.tag) { 183 184 case 1: 185 self.numbersRow1View.isHidden = false 186 self.numbersRow2View.isHidden = false 187 self.numbersSymbolsRow3View.isHidden = false 188 189 //change row 3 switch button image to #+= and row 4 switch button to ABC 190 self.switchModeRow3Button.setImage(UIImage(named:"symbols.png"), for:UIControlState.normal) 191 self.switchModeRow3Button.setImage(UIImage(named:"symbolsHL.png"), for:UIControlState.highlighted) 192 self.switchModeRow3Button.tag = 2 193 self.switchModeRow4Button.setImage(UIImage(named: "abc.png"), for:UIControlState.normal) 194 self.switchModeRow4Button.setImage(UIImage(named: "abcHL.png") , for:UIControlState.highlighted) 195 self.switchModeRow4Button.tag = 0; 196 197 198 case 2: 199 self.symbolsRow1View.isHidden = false 200 self.symbolsRow2View.isHidden = false 201 self.numbersSymbolsRow3View.isHidden = false 202 203 //change row 3 switch button image to 123 204 self.switchModeRow3Button.setImage(UIImage(named: "numbers.png"), for:UIControlState.normal) 205 self.switchModeRow3Button.setImage(UIImage(named: "numbersHL.png"), for:UIControlState.highlighted) 206 self.switchModeRow3Button.tag = 1 207 208 default: 209 //change the row 4 switch button image to 123 210 self.switchModeRow4Button.setImage(UIImage(named: "numbers.png"), for:UIControlState.normal) 211 self.switchModeRow4Button.setImage(UIImage(named: "numbersHL.png"), for:UIControlState.highlighted) 212 self.switchModeRow4Button.tag = 1 213 214 215 } 216 217} 218} 219 220

試したこと

サンプルプログラムには、キーボードのビューがKeyboard.storyboardが梱包されていたのでこちらを取り込みました。
https://github.com/bjhstudios/iOSCustomKeyboard

@IBOutletとstoryboardの接続がうまくできてないのかと思い、spaceButtonとの接続を解除→再接続してみたが、事象は再現してしまいました。

元のサンプルプログラム内ではUIButtonオブジェクトを生成しなくても実行できるのですが、私がSwiftに転記したバージョンでは、self.spaceButtonがnilになっているので、ここで実行時エラーになり止まってしまったようです。

補足情報(FW/ツールのバージョンなど)

Xcode 9.2を使用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

あくまで推測になってしまいますが、おそらくKeyboard.storyboardの取り込み方などでファイルの紐付けがうまくいっていないのかなと思います。
spaceButtonとの接続解除、再接続についてですが、storyboardから直接コードとの接続をしましたでしょうか。
(以下のような感じでswiftコードと直接つなげる。storyboard内でのつなぎだとobjective-c側とつながってしまっているようなことが起こるかも)
[Xcode][IB] IBOutletやIBActionをマウス操作で接続

また、storyboardについて一度削除をして、新しいプロジェクト内で新しく作ったstoryboardにいちから自分でファイルを作成してみる。もしくはstoryboardファイルのみプロジェクト内にコピーしてきてそこから入れ込むのようなかたちでもいけるかもしれません。
(取り込み方について、どのように取り込んだのかがわからないため、すでにそのようにして取り込んでいるかもしれませんが)
新しいstoryboardを作成する際には全部作成してから全部をつなぎこむと大変だと思いますので、spaceButtonのみ配置してつないでみる。(一番最初に呼ばれる部品がspaceButtonだと思いますので、そこをつないでnilになっていなければ一から作成すれば大丈夫と判断できる。)

カスタムキーボード作成についての内容はその他についてこちらに詳しい内容がのっていましたご参考までに(すでに参照済みかもしれませんが)
iOSカスタムキーボードの作り方

以上のようなことを試しても直らなかった場合、私の方でも実装試してみようと思いますのでコメントください。

投稿2018/08/01 09:38

razuma

総合スコア1313

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

razuma

2018/08/01 09:40

もしくはプロジェクトごとどこかにあげていただければそちらの方で直してみようと思います。
sacakoro

2019/01/20 02:55

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問