前提
tableViewを軽くするために、一回読み込んだ画像をキャッシュして再表示する時にNSMutableDictionaryでハマったのでメモ。
ハマったポイント
最初に画面表示したときはNSMutableDictionaryが読めたのにスクロールしてcellForRowAtIndexPath:が再度呼ばれたときにNSMutableDictionaryにアクセスしようとするとEXC_BAD_ACCESSとなってアプリが落ちる。
落ちたソース
- (void)viewDidLoad {
[super viewDidLoad]
dic = [NSMutableDictionary dictionary];
}
〜 中略 〜
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
〜 セルの再利用とかごにょごにょ 〜
//再読み込みするとここで落ちる
if([self.dic objectiveForKey:indexPath]){
cell.imageView.image = [self.dic objectiveForKey:indexPath];
}else{
[self.dic setObject:image forKey:indexPath];
cell.imageView.image = [self.dic objectiveForKey:indexPath];
}
}
原因
落ちたときのログを見てみると
アクセスしようとしたインスタンスはすでにdeallocされてるよ!!
との表記。。。
人為的にreleaseしてないよ!!とおもいながらappleのリファレンスを見てみると。
NSDictionaryにdictionaryの表記が!!!
そこには
このメソッドは空の可変NSDictionaryを返すよ!
ただ一時的な利用以外はちゃんとalloc initしてね!
との表記。
後々話を聞いてみるとdictionaryでインスタンスを生成するとautorelease対象となってしまうらしい。
勉強不足でautoreleaseでreleaseされるタイミングはよくわかっていないが
ざっくりと誰もそのインスタンスを参照しなくなったら勝手にreleaseされるものだと思っている。
推測だが画面が最初に表示されるタイミングはviewDidLoadでインスタンスを生成してtableViewの初回表示までは参照されていたが
表示し終わったあと誰も参照してないから勝手にreleaseされたものだと思われる。
修正方法
appleのリファレンスどおり一時的利用以外の利用をしたいため
ちゃんとalloc initしてあげたら落ちなくなった。
dic = [[NSMutableDictionary alloc]init];
まだまだ勉強不足でつらい。。。
いっぱいソース書くぞー
追記(9/13)
プロジェクト自体がMRC環境でした。
記述していなかったですが
- (void) dealloc{
[dic release];
しています。