相変わらず EXC_BAD_ACCESS で慌てる自分がいます。
EXC_BAD_ACCESS ググっても日本語で書いているものはかなり古い記事が多いので、誰かのために書いておきます。
環境はXCode 7.2.1 です。
NSZombieEnabled
まずはゾンビオブジェクト(解放されたオブジェクト)へのアクセス時に止まる様にしてみます。
[Edit Schema] – [Diagnostics] で [Enable Zombie Objects] にチェックします。
以前は、Arguments に NSZombieEnabledを追加、なんてしてた気がしますが、XCode 7の今はこうするみたいです。
おおよその場所が特定できたらブレークポイントを貼って色々見てみますが、今回の私のケースではそれでは全く原因が判りませんでした。
ARC以前のObjective-Cと比べるとSwiftになってから格段に楽になったというか、オプショナル型を正しく活用すればあまりクラッシュに遭遇する事は無くなりました。
ただライブラリの作りの都合上で暗黙的アンラップ型(Implicitly Unwrapped Optional)を使わざるを得ないケースも多々あり、今回そのへんが原因かなと思って一生懸命調べてたけど全然外してました。
デバッグは思い込みダメ。絶対。
shell malloc_history
昔はデバッガに shell malloc_history ってやってた気がしますが、今はこんなんが出るだけです。
error: ‘shell’ is not a valid command.
error: Unrecognized command ‘shell’.
どうやらInstrumentsでやれって事みたいです。
Instruments で Zombies を調べる
XCode 7 で [Product] – [Profile] をクリックします (または⌘+i)
[Choose a profiling template for] で [Zombies] を選択し、[Choose]をクリックします
赤丸(Record)ボタンをクリックします
実機やシミュレータを操作してEXC_BAD_ACCESSを再現させます
再現したら出る[Zombie Messaged] の矢印的なボタンをクリックします
EventType が Zombie、 RefCt が-1のクラスとメソッドが特定出来ました
あとはこっから類推して実際のコードであたりをつけてデバッグします。
因みに今日の自分の場合、色々試している中でAVCaptureDeviceにaddObserverしたりしたのを中途半端に消し忘れてたのが原因でした。半日無駄にしました。