初めてのiPhoneアプリ開発で、大変だったこと 4メモリリークとFMDB
iPhone版宅建アプリをリリースするにあたり、絶対に乗り越えなければならないハードルが、今回書いたエラーでした。
Adnrdoiであれば、基本的にGooglePlayは審査なしでアプリをリリースできるので、たまにエラーが出るくらいでは公開取り消しにもなりません。
ところが、iPhoneアプリの場合、AppStoreにリリースする前に、appleの審査があります。
その審査基準の一つに、アプリが停止しないこと、というのが!
とすれば、エラーがたまに出る状態で申請しても、たっぷり時間をかけた上でリジェクトされるだけです。
そのため、なんとかこのエラーは解決しなければなりません。
エラーの原因は、メモリリーク?
宅建アプリを作ってだいぶ後半になった頃、エラーが起きるようになりました。
そのエラーが発生する条件が、TOP画面からランダムボタンを押したときや、分野別や復習の問題リストから問題を選んだときや、問題を解く画面からTOP画面に戻ったときにエラーが生じるなど、バラバラです。
さらに、さきほどエラーが生じたときは、7回ほど画面を行き来したときだったのに、今回は15回ほど画面を行き来したところでエラーが起きた、という具合にバラバラなのです。
その上、エラーが発生したときのコードをみたり、それをキーワードにしてGoogleで検索しても、解決策がみつかりません。
となると、自分なりに分析してエラーの原因をさぐるしかありません。
これまでのandroidアプリ開発の経験を踏まえると、エラーのタイミングがバラバラだから、メモリ関係が原因の気が。
メモリの使用量が限界になってエラーとなると考えると、その時々でメモリの使用量は異なるため、バラバラなエラーのタイミングも説明がつきます。
そこで、メモリリークについて調べました。
ARC時代のメモリリーク対策
iOS5から本格的に使われるようになったのが、ARC(AutoReferenceCounting)。
これまでは、メモリ対策として、使わなくなったオブジェクトの参照を切るためにわざわざreleaseを自分で書かなければなりませんでした。
それが、ARCがあると、自動で参照を切ってくれるという!
ようするに、ARCを有効にすればメモリ管理は自動でやってくれるという!
とはいえ、ARCも完全ではありません。
そこで、手動で参照を切ることもあるらしいです。
例えば、画面遷移するときに、viewDidDisappearが呼ばれるので、その中で、ButtonやLabelにnilを入れて参照を切る。
さらに、[self.オブジェクト名 removeFromSuperview]でviewから外すという。
これを実践してみたところ、画面遷移するときに、TableViewが空っぽになったり、目に見えてメモリ使用量が減った気がしました!
あとは、for文やwhile文で繰り返し処理する文の中で、NSStringなどのオブジェクトを宣言する場合、auoreleasepool{}を書く。
他にも、循環参照を防ぐために、strongの変数=strongの変数にしないなど。
たくさんのサイトをみましたが、メモリ管理について、特にお世話になったのは、こちらの2つのサイトです!
ありがとうございました!
qiita.com
blog.it.churaumi.tv
さらに、エラーの原因をさぐるために、詳細なログが表示されるようにコードを追加する必要があります。
それについて、こちらのサイトのお世話になりました!
ありがとうございました!
http://www.zero4racer.com/blog/480www.zero4racer.com
エラーの原因は、メモリリークではなく、imageview
メモリ管理もやったところで、それでもエラーが解消されません。
今さらですが、冷静に考えてみると、まだシンプルな機能しかつけていないにもかかわらず、メモリリークが起こるはずがないです。
そこで、また別の原因をさぐることにしました。
ひとまず、現在リリースされている、他の宅建アプリを分析してみて、偶然エラーが発生することはないのか、検証してみました。
ところが、一切エラーが生じません。
そこで、他のアプリを分析したところ、共通点が見つかりました。
それは、問題を解く画面で、画像をほとんど使っていないというものです。
TOP画面では画像を使っているのですが、問題を解く画面では、デフォルトのボタン等を使っているアプリばかりです。
ひとまず、これらのアプリをマネしてみようと思い、問題を解く画面を変更することにしました。
まずはヘッダーを、これまではimageviewで画像を使っていたのですが、それを全てコードだけで表現するようにしてみました。
変更前(ヘッダーに画像を使っている)
変更後(ヘッダーがコードのみ)
そうしたところ、なんと、エラーが全く発生しなくなったのです!!
フッターの回答ボタンは、imagebiewではなく、buttonの背景として画像を使っているのですが、そちらは原因ではありませんでした。
どうやら、imageviewに何か原因があったようです。
いまだに、どういう理由か正確にはわかりませんが、imageviewには気をつけた方がいいです!
FMDBのちょっと注意すべきこと
iPhoneアプリでデータベースを使う場合、デフォルトで搭載されているCoreDataという選択肢と、ライブラリを導入するFMDBという選択肢があります。
CoreDataは、使いづらいと評判が悪いです。
それに対し、FMDBはすこぶる評判が高いので、FMDBを使っています。
ところが、FMDBを使っていたら、ログに大量のエラーがみつかりました!
原因はよくわかりませんが、while文の条件として[result next]をすると、このエラーがなくなります。
そのため、FMDBを使うときには、while([result next]){}がオススメです。
アプリが突然エラーになる原因がimageviewと判明するまでは、FMDBも疑っていました。
そのため、CoreDataにしなければいけない、と考えていたときもあったのです。
このようなこともありましたが、ついにエラーの原因がみつかり、それ以降エラーが発生しなくなりました!
エラーが解消されるまで、4日間を費やしました!