LDR touchではオフラインでも読めるようにフィードをキャッシュする仕組みがあります。
キャッシュするところのコードはだいたい以下のような感じになっています。
フィードのリストから、IDを取り出し、対応するエントリーのデータをダウンロードします。
- (void)saveEachEntries { LDRTouchAppDelegate *sharedLDRTouchApp = [LDRTouchAppDelegate sharedLDRTouchApp]; LDRManager *loginManager = sharedLDRTouchApp.loginManager; NSDictionary *feed; for (feed in feedList) { if ([self isCancelled]) { break; } NSString *subscribe_id = [NSString stringWithFormat:@"%@", [feed objectForKey:@"subscribe_id"]]; NSDictionary *entries = [loginManager loadEntries:subscribe_id]; [self saveEntries:entries]; } }
このコードには問題があり、エントリーデータを格納するオブジェクトが、ループを終了しない限り解放されないため、未読のフィードが大量にある場合は、メモリが足りなくなる恐れがあります。
自動解放プール(NSAutoReleasePool)はイベントループが一回りするたびにオブジェクトを解放します。
ループ中はイベントループに戻らないので、この間に作られた一時オブジェクトは解放されません。
この部分です。
NSDictionary *entries = [loginManager loadEntries:subscribe_id];
上のようにallocを使わずに生成されるオブジェクトは、autoreleaseされているので、releaseを送ってしまうと後で二重解放となりクラッシュしてしまいます。
このような場合は、ループの中で自動解放プールを作り、ループが一周するごとにオブジェクトを解放するようにします。
for (feed in feedList) { if ([self isCancelled]) { break; } NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSString *subscribe_id = [NSString stringWithFormat:@"%@", [feed objectForKey:@"subscribe_id"]]; NSDictionary *entries = [loginManager loadEntries:subscribe_id]; [self saveEntries:entries]; [pool release]; }
現在の時点で公開中のLDR touchは自動解放プールを作っていないので、未読フィードが多い場合メモリが足りずにクラッシュすることがあります。
上記の修正と、レートやフォルダ別表示に対応した新バージョンを、先ほど提出しました。
普通に審査を通過すれば、7〜9日でリリースされる予定です。