予備知識ゼロからiOSアプリを開発できるようにしよう!というのがこの「ゼロから始めるiOSアプリ開発」です。今回はリストを表示するのにぴったりなTableViewを使いつつ、実際にiPhone上でアプリを起動してみます。かつてはiPhone上でアプリを動かすには年間1万1800円を支払ってApple Developer Programの会員になる必要がありましたが、2015年からは無料で行えるようになっています。

「コードを書かずにアプリを作ってみる」という第1回の記事は以下より。

ゼロから始めるiOSアプリ開発「ボタンで画面を切り替えるアプリ」 - GIGAZINE



前回までと同様に新規プロジェクトを作成していきます。プロジェクトには「tableView」と名付けました。



「Main.storyboard」を開き、右下から「Table View」をドラッグ&ドロップで画面に配置し、「Constraints」を使って位置と大きさを決めます。下部に「TextField」と「Button」も配置しておきます。また、分かりやすいように背景の色をオレンジにしておきました。ここまでの手順は、第3回までの記事で確認できます。



続いて先ほど配置したテーブルビューの中に「Table View Cell」をドラッグ&ドロップで配置します。



そして「alt+command+enter」を同時に押してアシスタントエディターモードに入り、Table Viewを「control+ドラッグ」でViewControllerに接続します。



名前は何でも良いのですが、今回は「contentTable」と名付けて「Connect」をクリックしました。



また、下部に配置した入力欄とボタンもそれぞれViewControllerに接続します。ボタンを接続する際は「Action」を選択し、コードに「@IBAction」と表示されているか確認します。



もう一度テーブルビューをcontrol+クリックし、今度は左の「View Controller」までドラッグします。



接続の種類を尋ねられるので「dataSource」を選択。これはセルに表示するデータをどこで設定するかという項目です。今回は「View Controller」に接続したので、この画面と対応しているクラスである「ViewController」でデータを設定します。



もう一度Table Viewと左のView Controllerをcontrol+ドラッグで接続し、今度は「delegate」を選択します。これはテーブルビューに、セルがタップされるなど何らかのアクションがあった場合の処理をどこに書くかを設定するものです。さて、これでTable Viewから合計3つの接続が行われました。このように、テーブルビューを使う際には基本的にこの3つの接続を行う必要があります。



・「signal SIGABRT」

まだパーツを接続しただけですが、ここで再生ボタンをクリックしてアプリを動かしてみます。すると、「signal SIGABRT」という名前のエラーがでてアプリが停止します。この「signal SIGABRT」という表示は単にエラーが発生した程度の意味合いしか持っていないため、どういう理由でエラーが発生したのかは別の場所を見る必要があります。それは下の画像にあるように、アプリを動かした際に表示されるログです。万が一表示されない場合は右上のマークが青くなっているかチェックしてみて下さい。



このログにどういうエラーでアプリが停止したのかが記録されています。ログに残っている謎の文字列をしばらくさかのぼると、「*** Terminating app due to……」という部分があり、その後ろに理由が表示されています。アプリが停止した理由をGoogleで検索する場合、このあたりの文字列が大きなヒントになります。「signal SIGABRT」で検索しても欲しい情報はおそらく見つからないので注意してください。



さて、Table ViewのデータソースとデリゲートにViewControllerを選択したわけですが、公式のドキュメントによると、データソースとデリゲートとなったクラスは必ず「UITableViewDataSource」と「UITableViewDelegate」というプロトコルを採用しなければいけません。前回「UIImagePickerControllerDelegate」と「UINavigationControllerDelegate」でやったように、ViewControllerの後ろに書き加えていきます。



するとなにやらエラーが出ます。「Fix」をクリック。



すると2個の関数が追加されました。これはデータソースに設定したクラスに必須となる関数で、テーブルビューに表示するセルの数を決める関数とそれぞれのセルの表示を決める関数です。



まずはセルの情報を持っておくための配列「tableContents」を用意します。そして先ほど追加された2個の関数のうち、戻り値が整数型であることを示す「-> Int」となっている方に「return tableContents.count」と書き加えます。これでテーブルのセル数は配列の長さと同じになります。



次にもう一方のセルでセルの表示を設定します。

let cell = tableView.dequeueReusableCell(withIdentifier:"TableViewCell")!
cell.textLabel?.text = tableContents[indexPath.row]

return cell


これは配列「tableContents」の「セルの位置に対応する」場所に格納されている文字をセルに表示するというコードです。



ストーリーボードのテーブルビューのセルの設定の三角マーク「Attributes inspector」のページにある「Identifier」に、上のコードの「"TableViewCell"」と全く同じ文字列を入力しておきます。同じ文字列であれば何でも大丈夫です。



続いてボタンを押した際の動作を設定していきます。まず、セルに表示する情報を格納する配列に入力欄の文字を追加します。そして入力欄を空に戻し、最後にテーブルを再読込します。



・iPhone上でアプリを動かす

まずXcodeにApple IDを登録する必要があります。メニューの「Xcode」から「Preferences...」をクリック。



「Accounts」タブの左下にある「+」ボタンをクリックし、「Apple ID」を選択して「Continue」をクリックします。



Apple IDとパスワードを入力して「Sign In」をクリック。これは普段App Storeでアプリをダウンロードする時に使用しているIDとパスワードです。



追加に成功したら左上の赤いボタンで設定画面を閉じます。



左のナビゲーターからプロジェクトファイルを選択し、「Team」の欄から先ほど設定したアカウントを選択します。その後、上の「Bundle Identifier」が世界で1つのものになるように後ろに文字を付け加えます。他の人が作ったアプリとかぶっているとエラーになります。そして、シミュレーターを選択する部分をiPhoneとMacをUSBで接続すると表示される「iPhone」に変更し、再生ボタンをクリックします。



初回は必ず下の画面のようなエラーが出てアプリを起動できません。



iPhoneの設定画面より「一般」をタップし……



下の方に表示される「デバイス管理」をタップ。



「"……"を信頼」と書かれた部分をタップすると表示される確認画面でもう一度「信頼」をタップします。



もう一度アプリを起動してみると見事アプリの起動に成功しました。しかしキーボードが邪魔でボタンが押せません。



StackOverFlowに「キーボードの高さが変わったときに、入力欄と画面の下端の距離をキーボードの高さにする」という方法が載っていました。まずviewDidLoad()に

NotificationCenter.default.addObserver(self,
selector: #selector(self.keyboardNotification(notification:)),
name: NSNotification.Name.UIKeyboardWillChangeFrame,
object: nil)


と記入してキーボードの高さが変わるたびにkeyboardNotification()を呼び出すという設定を行い、続いてviewDidLoad()の外側に

@objc func keyboardNotification(notification: NSNotification) {

if let userInfo = notification.userInfo {

let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
let endFrameY = endFrame.origin.y ?? 0
let duration:TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue ?? 0
let animationCurveRawNSN = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
let animationCurveRaw = animationCurveRawNSN?.uintValue ?? UIViewAnimationOptions.curveEaseInOut.rawValue
let animationCurve:UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)
if endFrameY >= UIScreen.main.bounds.size.height {

self.keyboardHeightLayoutConstraint?.constant = 0.0
} else {

self.keyboardHeightLayoutConstraint?.constant = endFrame?.size.height ?? 0.0
}

self.keyboardHeightLayoutConstraint2?.constant = self.keyboardHeightLayoutConstraint?.constant
UIView.animate(withDuration: duration,
delay: TimeInterval(0),
options: animationCurve,
animations: { self.view.layoutIfNeeded() },
completion: nil)
}

}


と「キーボードの高さを取得してconstraintを適切に設定」する部分を記入します。そして通知を解除する処理を

deinit {

NotificationCenter.default.removeObserver(self)
}
のように書いておき、最後に入力欄とボタンの下のスペースを設定するconstraintをそれぞれ「keyboardHeightLayoutConstraint」と「keyboardHeightLayoutConstraint2」という名前でコードに接続すれば準備完了です。



もう一度実行してみると、今度はキーボードの出現に合わせて入力欄とボタンが上にスライドしてくれました。



次回はライブラリ管理ツールである「CocoaPods」を使ってみます。