先日iOS 10用にリニューアルしたアプリを公開したところ、「クラッシュするよ」との指摘をもらいました。詳しく聞いてみると、使っている機種はiPad Retina(4th Generation)とのこと。
開発中にiPad mini 2(retina)の実機とiPad Air2/Proのシミュレータで動作確認はしていたので、iPad Retinaでだけ動かないのは意外でした。
iPad Retinaのシミュレータで動かしてみると、確かに特定の画面でクラッシュします。エラー内容は悪名高き「EXC_BAD_ACCESS」。これだけではさっぱりわからないので、特定のために設定をします。
まず、Zombie Objects。設定の仕方が、Xcode 7あたりから大きく変わっていて、古い情報(「Arguments」タブの「Environment Variables」に「NSZombieEnabled = enable」を追加)を見てしまうとうまく動作しません。Xcode 8.2では、Edit Scheme… から下記のチェックボックスで指定します。
これを設定したところエラーメッセージが変化しました。
2017-01-08 11:58:14.444 DuelCalculator[64620:2819605] *** -[_NSCopyOnWriteCalendarWrapper release]: message sent to deallocated instance 0x79673240
既に存在しないオブジェクトを更にreleaseしようとしている、くらいのことはわかりました。しかし、オブジェクトのポインタのアドレスしかわからず、具体的にソースコードのどの部分かも表示してくれません・・
こちらの方法で、目ぼしいところのオブジェクトのアドレスを表示してみたりしましたが、やはりはっきりせず。
ここまで来てやっと具体的なメソッドがわかったので、修正を行います。
しかし今回のバグは、iPad Retinaだけに発生するということで、なかなか修正方法がわかりません。修正しつついろいろググっているうちに、下記の情報にたどり着きました。
NSCalendar *cal = [[NSCalendar currentCalendar] autorelease];
これがなぜiPad Retinaでだけ動作しないのかわかりませんが、恐らくアーキテクチャが32bitのためではないかと推測されます。これを、下記に直したところ、無事動きました。
NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
今後はiPad Retinaのシミュレータでも一通り動かさないといけないですね。。
そして思いたち、他の32bitアーキテクチャ(iPhone 4s)のシミュレータで確認してみたところ、やっぱり落ちました。iPhone 4s/5/5cなどをお使いの方すみません。。Appleには既に審査依頼したので、そのうち更新されると思います。
・追記
カレンダーのインスタンス化の仕方は気をつけないといけないようですね。
http://qiita.com/moriteru/items/effb1b8c4affb6d33c1a