AFNetworking 2.0 にアップデートしたばかりで、データをダウンロードして Core Data に挿入するコードを書き直しています。
JSON データ ファイル (10 ~ 200 MB のファイル) をダウンロードしてディスクに書き込み、バックグラウンド スレッドに渡してデータを処理します。以下は、JSON をダウンロードしてディスクに書き込むコードです。これを (データを処理することさえせずに) そのまま実行すると、アプリは強制終了されるまでメモリを使い果たします。
データが入ってくるとメモリに保存されていると思いますが、ディスクに保存すると、なぜメモリに残るのでしょうか? 自動解放プールがこれを処理するべきではありませんか? また、responseData と downloadData を nil に設定しました。ここで私が間違っていることが露骨に明らかなことはありますか?
@autoreleasepool
{
for(int i = 1; i <= totalPages; i++)
{
NSString *path = ....
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:path]];
AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
op.responseSerializer =[AFJSONResponseSerializer serializer];
[op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject)
{
//convert dictionary to data
NSData *downloadData = [NSKeyedArchiver archivedDataWithRootObject:responseObject];
//save to disk
NSError *saveError = nil;
if (![fileManager fileExistsAtPath:targetPath isDirectory:false])
{
[downloadData writeToFile:targetPath options:NSDataWritingAtomic error:&saveError];
if (saveError != nil)
{
NSLog(@"Download save failed! Error: %@", [saveError description]);
}
}
responseObject = nil;
downloadData = nil;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DLog(@"Error: %@", error);
}];
}
[mutableOperations addObject:op];
}
NSArray *operations = [AFURLConnectionOperation batchOfRequestOperations:mutableOperations progressBlock:^(NSUInteger numberOfFinishedOperations, NSUInteger totalNumberOfOperations) {
DLog(@"%lu of %lu complete", (unsigned long)numberOfFinishedOperations, (unsigned long)totalNumberOfOperations);
} completionBlock:^(NSArray *operations) {
DLog(@"All operations in batch complete");
}];
mutableOperations = nil;
[manager.operationQueue addOperations:operations waitUntilFinished:NO];
ありがとう!
編集#1@autoreleasepool
完全なブロック内に を追加すると、メモリ使用量が少し遅くなるように見えましたが、それでも蓄積され、最終的にアプリがクラッシュします。