【iPhoneアプリ開発入門】デバッグのやり方
iOSアプリのデバッグのしかたについて説明します。
まずはXcodeでプロジェクトを作成します。どのテンプレートからプロジェクトを作ってもデバッグ方法は同じですが、ここでは「Master-Detail Application」(Swift) を前提に進めていきます。プロジェクトの作り方は【iPhoneアプリ開発入門】Xcode操作だけでHello, Worldを表示をご覧ください。
iOSアプリのデバッグは、実機で実際に動かしてデバッグすることも、Mac上のシミュレータで動かしてデバッグすることもできます。
目次
目次
実機でのデバッグ作業
以前は、勉強等の目的であっても実機で自作iOSアプリを実行するためには Developer Program に加入(有料)する必要がありました。しかし Xcode7 以降では無料で実機での実行ができるようになりました(App Store で公開するには引き続き Developer Program への加入が必要です)。
実機でデバッグを開始する手順は次の通りです。デバッグの進め方は後述します。
iOSデバイスとMacをLightningケーブルで接続
初回接続時はXcodeがデバイスの情報を何か読み取るようで、少し待つ必要があります。
Xcodeの左上のメニューにデバイス名が出てくるので、それを選ぶ
(OS Version lower than deployment target)となっている場合
メニューに出てくるデバイス名に (OS Version lower than deployment target) と表示されている場合、プロジェクトの設定で「Deployment Target」をデバイスのOSバージョンに合わせます。
実行
Xcode左上の ▶︎ のボタンを押して実行します。
シミュレータでのデバッグ
シミュレータは実機と微妙に挙動が異なることが稀にあったり、遅かったり、実機でしか動作しない機能(カメラ等)もあるため、できるだけ実機でデバッグするようにしましょう。しかし、手元に無いデバイスの画面サイズでデバッグする等、シミュレータが必要になることもあります。
シミュレータでデバッグを開始するには、前述のXcode左上のメニューで「iOS Simulators」の中からシミュレートするデバイスの種類を選び、実行します。
デバッグの進め方
デバッグは、バグの内容によって臨機応変に様々な手段を用いる必要がありますが、ここではその中でも特によく使う「プリントデバッグ」と「ブレークポイントによる一時停止とステップ実行」について説明します。
プリントデバッグ
プリントデバッグとは、print文(関数)を用いてログを出力することによりデバッグを行う方法です。言語によってはprintではなく console.log(JavaScript) だったり NSLog(Objective-C) だったりと様々ですが、それらも含めてプリントデバッグと呼ぶのが一般的かと思います。Swiftにはprint関数があります。
「Master-Detail Application」のテンプレートから作ったプロジェクトで、MasterViewController.swift 41行目、insertNewObject 関数の冒頭に次の一行を挿入します。
1 2 3 4 5 6 7 8 |
[sourcecode lang="objc" firstline="40" highlight="41"] func insertNewObject(sender: AnyObject) { print("insertNewObjectが呼ばれました") objects.insert(NSDate(), atIndex: 0) let indexPath = NSIndexPath(forRow: 0, inSection: 0) self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) } [/sourcecode] |
これを実行し、アプリの画面右上の「+」ボタンを押します。Xcodeのウインドウ下部あるコンソールに「insertNewObjectが呼ばれました」と表示され、insertNewObject が呼ばれたことがわかります。
もし「+」ボタンを押してアプリの画面に何も変化が起きなかった場合、このようにprint文を挿入することで、そもそも insertNewObject が呼ばれてないのか、それとも insertNewObject は呼ばれているけど他の何かがおかしいのか区別できるようになります。プリントデバッグでは、これを様々な箇所で行いバグの原因を突き止めていきます。
なお、次のように \( と ) で囲むと変数の値をプリントすることもできます。
1 2 3 4 5 6 7 8 9 |
[sourcecode lang="objc" firstline="40" highlight="45"] func insertNewObject(sender: AnyObject) { print("insertNewObjectが呼ばれました") objects.insert(NSDate(), atIndex: 0) let indexPath = NSIndexPath(forRow: 0, inSection: 0) self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic) print("現在の項目数は \(objects.count) です") } [/sourcecode] |
ブレークポイントによる一時停止とステップ実行
Xcodeのエディタの左端に行数が表示されています。ここをクリックすると「ブレークポイント」を設定できます。
先ほどの41行目にブレークポイントを設定し、実行してみます。すると「+」ボタンを押した時にアプリの実行が停止し、次のような画面になります。
このようにして、ブレークポイントを設定した行でアプリの実行を一時停止することができます。このとき、カーソルが指している行の前の行まで実行が終わっていますが、カーソルが指している行はまだ実行されていません。
この状態で上の画像中の赤丸で示したボタンを押すと、カーソルが指している行が一行実行され、次の行にカーソルが移動します。これを「ステップ実行」と呼びます。print(“insertNewObjectが呼ばれました”) が実行されたので、コンソールに出力されたはずです。
コンソールの左側にはアプリ内の変数が表示されています。ここで「self」を開くとその下にいくつかの変数が展開されます。ここで「objects」に注目します。
[AnyObject] は objects の型です。0 values は objects に関する情報となります。整数型などでは値そのものが表示されますが、objects は配列なので要素数が表示されています。
ここでもう一度ステップ実行してみます。objects.insert(NSDate(), atIndex: 0) が実行され、1 value に変化しました。
objects を開くと、配列のインデックス0番に NSDate 型のオブジェクトが格納されていることがわかります。
このように、ブレークポイントによる一時停止とステップ実行で、実行中のアプリの状態を調べることができます。
まとめ
実機とシミュレータでのデバッグの開始のしかた、プリントデバッグ、ブレークポイントによる一時停止とステップ実行について説明しました。これだけでも十分デバッグできるようになりますが、Xcodeのデバッガには他にも様々な機能が搭載されており、それらを使いこなすことで短い時間でバグの原因を突き止めることができるようになります。開発の中でのデバッグが占める時間はかなり大きなものになるので、ぜひ使いこなせるようになってください。ブレークポイントで停止している時にいろんなボタンを押して何ができるのか試してみましょう。