[iOS][Swift]スタックトレース(コールスタック)を表示する2つの方法

公開日: : 最終更新日:2020/07/09 iOSアプリ開発 , ,

記事内に広告を含む場合があります。記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。

こんにちは、@akio0911です。

iOSアプリ開発で、スタックトレース(コールスタック)を表示する方法を2つ紹介したいと思います。

1. ブレークポイントを使う

コールスタックを確認したい箇所にブレークポイントを設定し、以下のように設定します。

  • Action: Debugger Command
  • コマンド: bt
  • Automatically continue after evaluating actions: チェック入れる

実行時に設定箇所を通過すると、以下のような内容がConsole領域に出力されます。

* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
  * frame #0: 0x000000010fd4c16c CallStack`ViewController.viewDidLoad(self=0x00007fcb824063d0) -> () at ViewController.swift:14
    frame #1: 0x000000010fd4c222 CallStack`@objc ViewController.viewDidLoad() -> () at ViewController.swift:0
    frame #2: 0x000000011099a01a UIKit`-[UIViewController loadViewIfRequired] + 1235
    frame #3: 0x000000011099a45a UIKit`-[UIViewController view] + 27
    frame #4: 0x000000011086298a UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 65
    frame #5: 0x0000000110863070 UIKit`-[UIWindow _setHidden:forced:] + 294
    frame #6: 0x0000000110875ebe UIKit`-[UIWindow makeKeyAndVisible] + 42
    frame #7: 0x00000001107ef37f UIKit`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4346
    frame #8: 0x00000001107f55e4 UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1709
    frame #9: 0x00000001107f27f3 UIKit`-[UIApplication workspaceDidEndTransaction:] + 182
    frame #10: 0x000000011478f5f6 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
    frame #11: 0x000000011478f46d FrontBoardServices`-[FBSSerialQueue _performNext] + 186
    frame #12: 0x000000011478f7f6 FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
    frame #13: 0x0000000113025c01 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    frame #14: 0x000000011300b0cf CoreFoundation`__CFRunLoopDoSources0 + 527
    frame #15: 0x000000011300a5ff CoreFoundation`__CFRunLoopRun + 911
    frame #16: 0x000000011300a016 CoreFoundation`CFRunLoopRunSpecific + 406
    frame #17: 0x00000001107f108f UIKit`-[UIApplication _run] + 468
    frame #18: 0x00000001107f7134 UIKit`UIApplicationMain + 159
    frame #19: 0x000000010fd4d2d7 CallStack`main at AppDelegate.swift:12
    frame #20: 0x000000011401f65d libdyld.dylib`start + 1
    frame #21: 0x000000011401f65d libdyld.dylib`start + 1

2. Thread.callStackSymbolsを使う

Thread.callStackSymbolsを使うと、その時点での現在のスレッドのコールスタックシンボルの配列を取得することができます。

以下、使用例です。

for symbol in Thread.callStackSymbols {
   print(symbol)
}

実際に使う時は、上記のコードをユーティリティメソッドなどにまとめてあげると良いでしょう。

上記のコードを実行した時の出力例を以下に示します。

0   CallStack                           0x0000000105eb8874 _TFC9CallStack14ViewController11viewDidLoadfT_T_ + 164
1   CallStack                           0x0000000105eb8ad2 _TToFC9CallStack14ViewController11viewDidLoadfT_T_ + 34
2   UIKit                               0x0000000106b0501a -[UIViewController loadViewIfRequired] + 1235
3   UIKit                               0x0000000106b0545a -[UIViewController view] + 27
4   UIKit                               0x00000001069cd98a -[UIWindow addRootViewControllerViewIfPossible] + 65
5   UIKit                               0x00000001069ce070 -[UIWindow _setHidden:forced:] + 294
6   UIKit                               0x00000001069e0ebe -[UIWindow makeKeyAndVisible] + 42
7   UIKit                               0x000000010695a37f -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4346
8   UIKit                               0x00000001069605e4 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1709
9   UIKit                               0x000000010695d7f3 -[UIApplication workspaceDidEndTransaction:] + 182
10  FrontBoardServices                  0x000000010a9ad5f6 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
11  FrontBoardServices                  0x000000010a9ad46d -[FBSSerialQueue _performNext] + 186
12  FrontBoardServices                  0x000000010a9ad7f6 -[FBSSerialQueue _performNextFromRunLoopSource] + 45
13  CoreFoundation                      0x0000000109190c01 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
14  CoreFoundation                      0x00000001091760cf __CFRunLoopDoSources0 + 527
15  CoreFoundation                      0x00000001091755ff __CFRunLoopRun + 911
16  CoreFoundation                      0x0000000109175016 CFRunLoopRunSpecific + 406
17  UIKit                               0x000000010695c08f -[UIApplication _run] + 468
18  UIKit                               0x0000000106962134 UIApplicationMain + 159
19  CallStack                           0x0000000105eb9bb7 main + 55
20  libdyld.dylib                       0x000000010a18a65d start + 1

ちなみにThread.callStackSymbolsを使うと、現在実行中のメソッドがどのメソッドから呼び出されたか?などを判定することができそうですが、そのようなコードを実際の実装に使うのはよくなさそうですね。

@akio0911はこう思った。


今回紹介したブレークポイントを使う方法はコードを編集しないので再ビルドせずに実行することが可能ですが、ブレークポイントに慣れていなければThread.callStackSymbolsがお手軽に使えるかなと思います。

シチュエーションや用途に合わせて、お好きな方を使ってみて下さい。

この記事を書いた人
あきお(@akio0911
派手髪iOSエンジニア。Twitterアカウントは@akio0911。YouTubeチャンネル「あきおチャンネル」にてiOSアプリ開発講座を公開中。著書に「iPhoneアプリ開発レシピ」「cocos2d for iPhoneレッスンノート」など。iOSアプリ開発をテーマとしたオンラインサロン「アプリ道場サロン」を運営。東京・大阪にてアプリ開発講座「アプリクリエイター道場」を主催。

関連記事

この記事が気に入ったら「いいね!」しよう

Twitterで更新情報をゲット!

PAGE TOP ↑