Raptor開発者ブログ

期限:2016年月日 やること:次のアプリをリリースする 資格の勉強法、アプリ開発、はてブロのカスタマイズのことを書きます!

初めての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で画像を使っていたのですが、それを全てコードだけで表現するようにしてみました。
 
変更前(ヘッダーに画像を使っている)
f:id:raptor36:20150731195959p:plain:w200
 
変更後(ヘッダーがコードのみ)
f:id:raptor36:20150804170228p:plain:w200
 
 
そうしたところ、なんと、エラーが全く発生しなくなったのです!!
 
 
フッターの回答ボタンは、imagebiewではなく、buttonの背景として画像を使っているのですが、そちらは原因ではありませんでした。
 
どうやら、imageviewに何か原因があったようです。
いまだに、どういう理由か正確にはわかりませんが、imageviewには気をつけた方がいいです!
 
 

FMDBのちょっと注意すべきこと

 
iPhoneアプリでデータベースを使う場合、デフォルトで搭載されているCoreDataという選択肢と、ライブラリを導入するFMDBという選択肢があります。

CoreDataは、使いづらいと評判が悪いです。
それに対し、FMDBはすこぶる評判が高いので、FMDBを使っています。

ところが、FMDBを使っていたら、ログに大量のエラーがみつかりました!

原因はよくわかりませんが、while文の条件として[result next]をすると、このエラーがなくなります。
そのため、FMDBを使うときには、while([result next]){}がオススメです。
 
 
アプリが突然エラーになる原因がimageviewと判明するまでは、FMDBも疑っていました。
そのため、CoreDataにしなければいけない、と考えていたときもあったのです。
 
 
 
 
このようなこともありましたが、ついにエラーの原因がみつかり、それ以降エラーが発生しなくなりました!
エラーが解消されるまで、4日間を費やしました!
 
 
 

QLOOKアクセス解析