昨今の開発環境ではブレークポイント設定や変数値の確認ができるソースレベルデバッガの存在は当たり前です。Xcodeももちろんそれを備えています。

※ デバッグのために不用意にNSLogを書きまくるのはコードが汚れるのでやめましょう。場合よってはソースレベルデバッガよりNSLogの方が有効な時もあります。それについても後述します。

Runした時に変数とデバッグコンソールが表示されるようにする

XcodeのメニューからPreferencesを開きBehaviorsタブを選択してください。

01_edited-2

RunningセクションのStartsを選択し、Show debugger withの項目をチェック。Variables & Console Viewを選択してください。こうすると実行した時に自動的にデバッガによる変数とコンソールが表示されます。

02-2

ブレークポイントの追加、削除

ソースファイルの行番号をクリックするとブレークポイントが貼られます。

03-1

ブレークポイントのコンテキストメニューからブレークポイントの削除(Delete Breakpoint)ができます。

04

またブレークポイントを適当な位置へドラッグ・アンド・ドロップして削除することも可能です。

06

Disable Breakpointはブレークポイントを一時的に無効にします。既存のブレークポイントをクリックした時も無効状態になります。この場合、ブレークポイントの色が薄くなります。

07-1

もう一度クリックすると再度有効になります。

変数値の確認

実行中にブレークポイントを設定したコードに到達すると、このようにブレークポイントの位置で実行停止します。

08

このときXcodeの下端の左側に現在の変数値、右側にNSLogや警告やエラーの内容が出力されます。

09_edited-2

クラスや構造体などは左端の三角を押すことで内容を展開出来ます。

10-1

ステップ実行

ブレークポイントで止まった状態で、プログラムを実行再開したり、1行ずつプログラムを実行するために、以下のボタンが用意されています。

12-1

  • 実行継続 実行を再開して次のブレークポイントで止まるまで実行継続する
  • ステップオーバー 1行ずつプログラムを実行する
  • ステップイン 現在の停止位置がメソッドである場合、そのメソッドの中に入る
  • ステップオーバー 現在の定位置がメソッドの中である場合、そのメソッドから外へ出る

この中でよく利用するのが、ステップオーバーです。1行ずつ実行することで変数の値が計算式やメソッドの戻り値の代入などで変化していくのを確認できます。これはデバッグに大いに役立ちます。

以下はブレークポイントから2回ステップオーバーを押して2行実行した状態。

11

変数の値確認などが終わって、実行再開したい時は実行継続を押します。

スタックトレース

ブレークポイントにより停止しているときは、Xcode左側は以下のように今いるメソッドの呼び出し元メソッドが順に並んで表示されています。これをスタックトレースといいます。

13

スタックトレースから呼び出し元のメソッドを選択すると、そのメソッドの呼び出し元へカーソルが合わさります。

14-1

15-1

この時、呼び出し元メソッドでのローカル変数やメンバ変数の値を確認できます。

16

ソースレベルデバッガを使った実践でのデバッグ方法

バグが起きるということは、変数がある場所で期待した値にならなかったことが原因だったり、意図しない条件分岐がなされたり、実装漏れだったりします。ソースレベルデバッガを使う場合、以下のようにデバッグすると良いでしょう。

  • まずはバグの原因が潜んでいそうな場所を目星をつけてブレークポイントを設定する(場合によっては複数箇所)
  • ブレークポイントで止まることを確認。通過すると思ったのにブレークポイントで止まらないかもしれない。その場合、そのコード以前までさかのぼってブレークポイントを設定し直す
  • ステップオーバーで1行ずつ実行しながら変数値の変化や条件分岐が正しく行われるかを確認
  • この時点でバグを発見したら修正
  • バグが発見できなければ他の怪しい箇所にブレークポイントを設定して、再度上記の作業を繰り返す

NSLogを使ったほうが良い場合

ソースレベルデバッガは大変便利なのですが、場合によってはNSLogでコンソールに出力される内容を追ったほうがわかりやすい場合もあります。たとえば、

  • タッチイベントが正しく処理されているか
  • 頻繁に通過するコードが怪しい場合

などは、ブレークポイントでいちいち止まるとデバッグがしづらくなります。

こういった場合はNSLogで出力したほうがデバッグしやすいかもしれません。いずれにせよ、NSLogを埋めることはコードを汚すことになります。デバッグが終わった後も、デバッグ用のNSLog出力が残っていて、デバッグコンソールに大量の出力があると、チーム開発で他の人に迷惑がかかります。

Gitなどでバージョン管理している時は、まずデバッグ前に作業に区切りをつけてコミットしてから、NSLogを埋め込みましょう。バグの原因がわかったら、リバートしてNSLogを全部なくしてしまって、バグ修正してコミットする、といったアプローチが良いと思います。他の人にも迷惑がかかりません。