【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

「 エラーが出た時の原因を探る方法がわからない… 」

「 問題解消に時間がかかってしまう… 」

そんな方におすすめしたいのが、デバッグ機能の活用です!

Swiftの機能である「print文」や、Xcodeが提供している「ブレークポイント」「poコマンド」「ウォッチポイント」「ステップ実行」など、これらのデバッグ機能を使うことでエラーや不具合が起きた時に素早く問題を発見解消することができます。

今回は、そんなエラーハンドリングに役立つ機能をご紹介していきます。

[ 本記事はこんな人におすすめ ]

・プログラミングにまだ慣れていない

・エラーや不具合の解消方法がわからなくて手が詰まってしまう

・Xcodeのデバッグ機能について知りたい

環境・バージョン

  > Swift 5.7.2

  > Xcode 14.2

  > macOS 12.5 Monterey

デバッグとは

「デバッグ」という言葉は、みなさんも一度は耳にしたことがあると思います。

デバッグについて、Wikipediaではこのように書かれています。

デバッグ(debag)とは、コンピュータプログラムや電気機器中のバグ・欠陥を発見および修正し、動作を仕様通りのものとするための作業である。サブシステムが密結合であると、1箇所の変更が別の箇所でのバグを作り出すので、バグの修正がより困難となる。

– Wikipedia デバッグ-

プログラムが狙いどおりに動作しているか、不具合は発生していないかをチェックする作業のことをデバッグと言うのですね。

プログラミング作業を進めていくうちに、

「この箇所のプログラムが正常に動いてない気がするな…」

「ここの変数の状態ってどうなってる…?」

など、コードのチェックがしたくなる機会はよく現れるでしょう。

Xcodeには手軽にデバッグ作業ができる便利な機能が備わっており、使えるようになるといざという時にも非常に便利です。この機会に少しずつ慣れていきましょう!

サンプルアプリの紹介

デバッグ機能を解説するために、SwiftUI対応のサンプルアプリを用意しました。

(+)ボタンを押すことで数字がカウントアップしていく、非常にシンプルな動作です。

こちらを使ってSwiftやXcodeのデバッグ機能を試していきましょう。

もちろん、お手持ちのプロジェクトを使っていただいても大丈夫です。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用
				
					struct ContentView: View {

    // テキスト表示される数字の値
    @State var number = 0

    var body: some View {

        VStack(spacing: 100) {

            Text("\(number)")
                .font(.system(size: 100))

            Button {
                // ボタンタップによる処理
                number += 1

            } label: {
                // ボタンのデザイン
                Image(systemName: "plus.app.fill")
                    .resizable()
                    .frame(width: 50, height: 50)
            }

        } // VStack
    } // body
} // View
				
			

下記の枠内の範囲は、(+)ボタンがタップされた時に実行されるアクション範囲です。

今回デバッグ機能を仕込むのは基本的にこの枠内なので、こちらに注目していただければ大丈夫です。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

print文の活用

簡易的にプログラムの実行動作をチェックできる機能として、「print」機能があります。

print文を使うことで、デバッグエリアに任意のメッセージ文を出力することができます。

サンプルコードのボタンアクション範囲にprint文を追加してみました。

シミュレータ「Command + R」で動作を確認してみましょう。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

ボタンをタップするたびに、デバッグエリアにメッセージが出力されていますね。

これだけでも、「ボタンがタップされるたびに、ボタンのアクションプログラムが正常に実行されている」ということが確認できます。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

print機能の動作が確認できたら、このprint文がどのように活用できるのかをみていきます。

if文(条件分岐)の動作をチェック

print文は、”ある位置のプログラム処理が実行されているか“を確認するのに便利です。

例えば、ボタンタップ時の処理にif文による条件分岐があったとします。

以下のコードは「もしnumberの値が5未満だったら」という条件分岐です。

条件に当てはまれば変数numberの値がプラス1され、print文が出力されます。

				
					            ...
            
            Button {
                // numberの値が5未満だったら
                if number < 5 {

                    number += 1
                    print("numberの値は5未満です。値を増加しました。")
                }

            } label: {
               
               ...
				
			

シミュレータ「Command + R」で確認してみましょう。

値が5以上になった時点で、ボタンタップによる値の増加が止まり、printメッセージの出力も止まっていますね。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

このようにprint文をif文の中に置いておくことで、「if文の条件判定が適用されているかどうか」をチェックすることができます。

一定範囲のプログラムの開始と終了をチェック

ある”ひとかたまり”のプログラムが、正常に処理が開始され、正常に終了したかどうかをチェックするのにもprint文は活用できます。

以下のコードでは、ボタンアクションに複数の処理を並べて、開始と終了をprint文で挟んでいます。

				
					            ...
            
            Button {

                print("処理が開始しました。")
                number += 1 // 処理1
                number += 1 // 処理2
                number += 1 // 処理3
                print("処理が終了しました。")

            } label: {
             
             ...
				
			

シミュレータ「Command + R」で確認してみます。

開始、終了、二つのprint文が正常に出力されていますね。

printで挟んだ複数の処理が正常に完了したことがわかります。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

プログラムは基本的に、上から下へ処理が実行されていきます。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

例えばボタンタップ時に、

開始メッセージは出力されたが、終了メッセージは出力されなかった」となった場合、

処理の実行途中に何らかの不具合が起きている可能性が考えられるということです。

今回のサンプルでは、目に見えて数字のカウントが確認できるので判別しやすいですが、

実際の開発では実行結果が目には見えないプログラム処理も多くあります。

不具合やバグが発生した時、その原因が”どこで発生しているのか“が非常に重要です。

print文を活用することで、不具合箇所の特定がしやすくなります。

変数の内容をチェック

“ある箇所の変数の値を確認したい”といった場面は多くあります。

print文を活用することで、ある地点での変数の値をチェックすることができます。

以下のコードでは、値の増加処理の”前と後”にprint文を置いています。

変数をバックスラッシュ「\」と「()」で囲むことで、文字列の中に変数の値を入れることができます。

バックスラッシュ「\」の入力方法 → 「Option + ¥

				
					            ...
            
            Button {

                print("計算処理前のnumber: \(number)")

                number += 1

                print("計算処理後のnumber: \(number)")

            }
            
            ...
				
			

カウントアップ処理の実行前の変数と、実行後の変数の値がデバッグエリアで確認できますね。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

ビューレイアウトにプリント文を置く

通常、ビューレイアウトの中にprint文を置くことはできません。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

しかし以下のように、let _ = print("...")と記述することで、ビューレイアウト内にもprint文を配置できるようになります。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

例えばListなどのビュー機能にも組み込むことができます。

ビューレイアウト内で処理されている値をチェックしたい時などに便利です。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

Xcodeのデバッグ機能の活用

プログラミングで用いる開発ツールの一つとして、「デバッガ」というものがあります。

デバッガはデバッグ作業をするためのソフトウェアツールであり、Xcodeにもデバッガが備わっています。

前項目のprint機能との違いとして、プログラム内にコードの記述をする必要なく、デバッグ作業を行うことができるという点があります。

Xcodeに搭載されているデバッガの使用方法をご紹介します。

ブレークポイント

ブレークポイントは、”任意の箇所でプログラムを一時停止“することができます。

コードの行番号をクリックすることで、ブレークポイントを打つことができます。

こちらのブレークポイント機能は、後述で解説するデバッガの起点となります。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

ブレークポイントを右クリックで、各種設定メニューが開きます。

メニュー項目の詳細は以下です。

◯Edit Breakpoint

ブレークポイントに名前を付けるなどの詳細設定ができます。

◯Disable (or Enable) Breakpoint

選択したブレークポイントの一時的な有効化・無効化を切り替えます。

◯Disable Other Breakpoint

選択箇所を除いたすべてのブレークポイントを一時的に無効化します。

◯Delete Breakpoint

選択したブレークポイントを削除します。

下記の例では、26行目、ボタンタップ時の処理位置にブレークポイントを置いています。

この場合、ボタンタップによって指定位置に処理が走ったタイミングで、処理が一時停止します。右側に出てる緑色のメッセージがブレークポイントによる一時停止の印です。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

ウォッチポイント

ウォッチポイントでは、ブレークポイントによる一時停止中に変数の中身をチェックすることができます。

デバッグエリアの左側フィールドがウォッチポイントです。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

ブレークポイントによる一時停止が発火したタイミングで、自動でウォッチポイントに変数情報が検出されます。

例のように、変数に複数の情報が格納されている場合は、左側の「>」をクリックすることで詳細が表示されます。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

poコマンド

ブレークポイントで一時停止中、デバッグエリアにコマンドを打つことで変数の中を確認できます。

前項目のウォッチポイントでは、思ったように変数情報が検出されない場合があります。

そういった場合にピンポイントで変数の中をチェックするのに便利です。

デバッグエリアに「po <変数名>」 と打ち込み、エンターキーを押すことで変数の情報検出を開始します。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

ステップ実行

ブレークポイントで一時停止中、任意の行までプログラムの実行を操作することができます。

ステップ実行には主に4種類の操作メニューがあります。

エラーの原因を調べてみよう!役立つデバック方法とprint文の活用

①再開                      :  一時停止を解除してプログラムを再開する

②ステップオーバー:  1行ずつ処理を進める

③ステップイン       :  1行ずつ処理を進める(関数がある場合、内部に入る)

④ステップアウト   :  関数を終了するまで処理を進める

①再開

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

ブレークポイントによる一時停止を抜けて、処理を再開します。

再開後、先の処理で他のブレークポイントが置かれている場合は、その地点で再び処理が停止されます。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

②ステップオーバー と ③ステップイン

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

両者とも、ブレークポイントによる停止位置から、1行ずつ処理を進めます。

両者の異なる点として、

②ステップオーバーは、ステップ進行時に関数が置かれていた場合、
関数の内部処理のチェックは飛ばして次の行に進みます。

③ステップインは、ステップ進行時に関数が置かれていた場合、
関数の内部へとチェックが移動します。

両者の動きの違いを確認するために、新規で関数「plusNumber」を作成しました。

+ボタンタップによる処理を引越しさせただけの、簡易的な関数です。

[ ボタンアクション処理を引越しさせた関数plusNumber ]

				
					        ...
        
        } // VStack
    } // body

    // ボタンタップ処理を関数内に移動
    func plusNumber() {
        print("計算処理前のnumber: \(number)")
        number += 1
        print("計算処理後のnumber: \(number)")
    }

} // View
				
			

[Before]

				
					         ...
          
           Button {

                print("計算処理前のnumber: \(number)")

                number += 1

                print("計算処理後のnumber: \(number)")

            } label: {
                // ボタンのデザイン
                Image(systemName: "plus.app.fill")
                    .resizable()
                    .frame(width: 50, height: 50)
            }

        } // VStack
    } // body
} // View
				
			

[After]

				
					            ...

            Button {

                // 関数plusNumberを呼び出す
                plusNumber()

            } label: {
                // ボタンのデザイン
                Image(systemName: "plus.app.fill")
                    .resizable()
                    .frame(width: 50, height: 50)
            }

        } // VStack
    } // body

    // ボタンアクションによる処理を引越しさせた関数
    func plusNumber() {
        print("計算処理前のnumber: \(number)")
        number += 1
        print("計算処理後ののnumber: \(number)")
    }

} // View

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

				
			

ブレーク後の、両者の動きを見比べてみてください。

ステップインでは、関数の内部へジャンプし、関数チェック終了後に呼び出し元に戻ってきていることがわかりますね。

[②ステップオーバーの動き]

関数の内部処理は追わない

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

[③ステップインの動き]

関数の内部チェックへ移動

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

④ステップアウト

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

③ステップインによる関数内部のチェック時に、途中で関数処理チェックをスキップできます。

「チェックしたい部分は見ることができたから、関数から抜けて呼び出し元に戻りたい」という時に便利です。

【デバッグ】エラーの原因を調べてみよう!Swiftのprint文とXcodeのデバッガの活用

まとめ

以上、Swiftのprint文とXcodeのデバッグ機能についての解説でした。

print文は比較的使っている方が多いかもしれませんが、Xcodeのデバッグ機能である「ブレークポイント」「poコマンド」「ウォッチポイント」「ステップ実行」これらを組み合わせることで、さらにプログラム処理の把握ができるようにでしょう。

ぜひ使いこなして、アプリ開発に役立てていただければと思います!

動画の紹介

\  SHARE  /

Twitter
Facebook
Email

✏️ アプリ開発が学べる勉強会を開催中! 

CodeCandyではアプリ開発を学ぶための勉強会を定期開催しています。
学習する習慣を身につけたい、他の参加者と作業したい、アプリ開発の基本をマスターしたい、という方のために無料で学べる勉強会です。
グループにメンバー登録して頂くと、イベント開催時にメールで通知されます。

▶️グループのメンバーとして参加する

徹底した基礎学習からマスターするiPhoneアプリ開発集中オンライン講座開講!

本書「iPhoneアプリ開発集中講座」を執筆している現役エンジニア講師陣が直接に指導!
基礎、課題実習で実践力を鍛えて、オリジナルアプリ公開までチャレンジ!
充実した転職支援もあるので、エンジニアへ転職したい人にもおすすめです!

まずは、現役エンジニアに相談できる無料相談をご利用ください。

\ Official /

By 中川 賢亮

2022年2月よりSwift学習を始め、4月からiOSアプリ開発オンラインスクール「CodeCandy」にてアプリ開発を学ぶ。 2023年10月に個人開発アプリ「unico」をリリース。現在はアプリの機能アップデートをしながら、スクール運営の技術ブログの執筆や、出版書籍の入稿チェック・デバッグにも携わる。