2010年11月08日

デバッグにクラッシュログを使う

まともな開発者なら常識なのかもしれませんが、最近になってここでやり方を知ったので、書いておきます。

デバッガで動作中に落ちたりすれば、簡単にスタックトレースを参照できるため、問題の特定はしやすいのですが、持ち歩いている最中に自作アプリが落ちた場合の問題箇所の特定は意外と難しいものです。

このときに使えるのがクラッシュログ( *.crash )です。iPhoneの場合、iTunesと同期したときに ~/Library/Logs/CrashReporter/MobileDevice/(iPhone名)/ にクラッシュログが保存されます。また、リリース後のアプリについては、iTunes Connectにある程度クラッシュログがあがってきます。このクラッシュログにはスタックトレースらしきものが保存されていますが、


Thread 0 Crashed:
0 libobjc.A.dylib 0x3002d7d8 0x3002b000 + 10200
1 TextInput_ja 0x34c94648 0x34c8e000 + 26184
2 TextInput_ja 0x34c92888 0x34c8e000 + 18568
3 UIKit 0x31e93e10 0x31e4d000 + 290320


こんな感じで、アドレスしか記録されていません。そこで、gdb と保存されている dSYM を使って、このアドレスから該当ソースコードのファイル名と行番号を取得することができます。

iPhoneの場合、armベースのため、使用するgdbは /Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin になります。

dSYMはプロジェクトディレクトリの build/(DebugまたはRelease)-iphoneos/ の下にあります。拙作のToToDoの場合、


$ cd ~/Documents/ToToDo/build/Release-iphoneos/ToToDo.app.dSYM
$ cd Contents/Resources/DWARF
$ /Developer/Platforms/iPhoneOS.platform/Developer/usr/libexec/gdb/gdb-arm-apple-darwin ToToDo


こんな感じで dSYM を読み込ませて gdb を起動します。たぶん何かをすれば、最後の行は gdb ToToDo と書けばよくなるようなのですが、方法が分かりませんでした。どなたか教えてください。

その後、クラッシュログのモジュール名の次のアドレスを指定して、info line *(アドレス) とすると以下のようにソースファイル名と行番号が取得できます。


(gdb) info line *0x0000a79a
Line 979 of "/Users/nlights-iapps/Documents/ToToDo/Classes/TDInputViewController.m" starts at address 0xa78e <-[TDInputViewController didReceiveMemoryWarning]+6> and ends at 0xa7a0 <-[TDInputViewController didReceiveMemoryWarning]+24>.


ということで、リリースしたアプリの dSYM は絶対取っておいたほうがいいですね。

symbolicatecrash というツールもあるようです。ここに簡単な説明がありました。
posted by iphone-dev at 00:04| 日記

2010年11月05日

現在のFirstResponderを取得する

現在のFirstResponderを取得するには、以下のコードが使えます。


UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *firstResponder = [window performSelector:@selector(firstResponder)];


しかし、これはプライベートAPIなので、これを使うとリジェクトの対象になってしまいます。

そもそも、FirstResponderを取得したい理由は、resignFirstResponderを実行したいだけの場合がほとんどです。その場合、以下の一行だけで要件は済んでしまいます。


[self.view endEditing:YES];


純粋にFirstResponderを取得するコードは、ここを参照してください。
posted by iphone-dev at 18:51| 日記