Swift プログラムのデバッグテクニック - ブレイクポイント、ランタイム変数検査

この記事では、一般的なバグ修正方法をいくつかご紹介します。

# 一般的なデバッグ手法

## print, print, print...

Printステートメントは常に役に立ちます。それにより、プログラムのランタイム中に変数を出力できます。

```swift
func dailyRoutine(){
    print(myCats)
    myCats.forEach { (cat) in
        print("猫の名前は\(cat.name)です。")
        cat.feed()
        cat.hug()
    }
}
```

## ブレークポイント

行番号をクリックしてブレークポイントを `Xcode` に設定できます。プログラムは、シミュレーターか接続したiOSデバイス上で実行しているとき、ブレークポイントに到達すると停止します。ブレークポイントには以下のようないくつもの種類があります。

### 通常のブレークポイント

通常のブレークポイントを作成するには、`Xcode` のコード行の行番号をクリックします:

![ezgif-2-df0a16ddb28f.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/a3619597-7e0f-16db-aefe-fc76afca46a4.gif)

プログラムが停止すると以下のようになります:

<img width="1308" alt="Screen Shot 2020-05-23 at 16.56.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/6636c9b5-378c-e5f2-3a6e-ab86827c7c1d.png">

### 条件付きブレークポイント

条件付きブレークポイントは、ある特定の条件を満たした場合にのみコードを停止させます。例えば、ネコの名前が "ネコノヒー" : の場合にのみ、プログラムの実行を停止させたいならば

![ezgif-2-ded322b7d123.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/eb402ca5-3477-d737-bffc-a901cf35c2da.gif)

<img width="460" alt="Screen Shot 2020-05-23 at 16.50.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/1ceaa004-4b90-91f6-1f1e-e51834d968d6.png">

1. 通常のブレークポイントの作成
2. 青ラベルをダブルクリックする
3. 条件フィールドに条件を入力する。ここでは `cat.name == "ネコノヒー"` と入力しました。

### 表示変数

ブレークポイントに来たらアクションを実行して、プログラムを停止しないこともできます。

```swift
print(cat.name)
```

上記コードは次のように置き替えることもできます。

![ezgif-2-3a86395ceed2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/fdbf79d0-12bc-dcb3-539c-1bc31d8b2303.gif)

<img width="459" alt="Screen Shot 2020-05-23 at 16.49.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/624dc665-859b-bd8c-00b3-1c9713820ac9.png">

1. 通常のブレークポイントを作る
2. `Add Action` ボタンをクリックする
3. `po cat.name` などのアクションを入力する。`po` がどのようなものであるかについては、次のパートで取り上げます。
4. トグルスイッチを、評価アクション後に自動的に継続するオプションに合わせる `Automatically continue after evaluating actions`

ブレークポイントに来てもプログラムは停止せず、猫の名前がコンソールに表示されます。

<img width="1849" alt="Screen Shot 2020-05-23 at 16.57.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/2217bf16-c37a-58a1-745d-9b667095d39a.png">

### Xcodeが組み込まれたランタイムデバッガ (po)

ブレークポイントでプログラムが停止した時は (通常のブレークポイント)、変数の値を調べて、変数値を変えて下さい。

例えばここにブレークポイントを置くことができます。

<img width="831" alt="Screen Shot 2020-05-23 at 16.54.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/7a90df82-e2e1-3f42-88f2-20db3093c9c2.png">

ブレークポイントでプログラムが停止した時は、コンソールウィンドウで命令を実行できます。

#### 変数を調べることができます。

ここでは、`po` は表示オブジェクトにあたります。

`po myCats`

![ezgif-2-5c651f6b6d79.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/7532f52b-d0db-d826-d756-1938fde2248b.gif)

`po myCats.count`

![ezgif-2-4a6e311fe684.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/fbe13418-4bc5-c42f-382c-94efe24b0cc7.gif)

`po myCats.first?.name`

![ezgif-2-4f432462041b.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/ae71f537-ff15-c021-0be1-4f7c8fb6e43f.gif)

#### 変数を変更することも可能です

```swift
po myCats.count //2
po myCats.append(.init())
po myCats.count //3
```

![ezgif-2-74bf7e847d7a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/2c3ce92f-0ee3-1286-4457-1fed48e8b5dd.gif)

### Xcode オーガナイザー

App Storeで既にプログラムが公開されていれば、Appleがクラッシュの情報を集めてくれます。

`Xcode` のトップメニューで、"Window"と"Organizer"をクリックしてください。

<img width="1204" alt="Screen Shot 2020-05-23 at 17.10.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/234c51a1-2f16-5127-4821-0798cabb06e2.png">

左側でApp Storeで既に公開しているアプリケーションをクリックして、トップの"Crashes"をクリックしてください。

<img width="570" alt="Screen Shot 2020-05-23 at 17.12.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/72df6463-0247-6341-bebe-889022f49bf7.png">

App Storeにある私のアプリで起きた実際のクラッシュに関するレポートをシェアしたいと思います。この問題はすでに解決済みです。

まずはバージョンのドロップダウンメニューをクリックしてバージョンを選択してください。

<img width="268" alt="Screen Shot 2020-05-23 at 17.14.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/b76dad02-6169-e908-bda7-a0230d9bfd5f.png">

実際に起きたソフトウェアのクラッシュのリストが表示されるかと思います。そのうちの1つをクリックして詳細を見てください。

<img width="1402" alt="Screen Shot 2020-05-23 at 17.15.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635330/8dc758aa-f75a-8eab-9c9c-742a2b16f393.png">

青色の "Open in Project" (プロジェクト内で開く) ボタンをクリックすると、自分のプロジェクトファイルを選択でき、どのラインでクラッシュがあったのかを教えてくれます。

### Metrics

これまでの記事で話したように、メトリクスをチェックしてメモリに問題がないかどうかを確認することもお勧めします。

[iOSアプリのメモリリーク (Memory Leak) の検出とデバッグの方法を、ネコに関するプログラムで学びましょう。(Reference Cycle 参照サイクル)](https://qiita.com/MaShunzhe/items/8073d32d7aee28578cab#メモリ問題の発見)

---

:relaxed: [Twitter @MszPro](https://twitter.com/MszPro)

:sunny: [私の公開されているQiita記事のリストをカテゴリー別にご覧いただけます。](http://mszpro.com/ioskiji/)
<img width="150" src="https://cdn.mszmagic.com/static-web-content/AppClipImage_small.png">