質問への編集: 2013 年 10 月 21 日 20:10 GMT
メソッドが呼び出される方法を以下に追加し、リークしているオブジェクトも「allDBObjects」です。これを削除して、以下の辞書を「NSMutableDictionary *objectsById」に変更すると、リークはありません。
質問への編集: 2013 年 10 月 21 日
この問題について数日過ごした後、私はそれに戻ってきました。これはすべて「解放の問題」( https://developer.apple.com/library/ios/technotes/tn2109/_index.html#//apple_ref/doc/uid/DTS40010274-CH1-SUBSECTION11 )にかかっていると思います。MKNetworkKit と AFNetworking 1.3.3 (MKNetwork Kit の代わりに AFNetworking を使用するように 1 つのメソッドを変更) の両方でテストしましたが、まだこれらのオブジェクトが完了ブロックでリークしています。ブロック内に自己への参照がなく、AFNetworking を使用すると、completionBlock が nil に設定されていることがわかり、[weakOp setCompletionBlock:nil] を設定して保持サイクルを手動で中断しようとしました。
EDIT:以下のコードサンプルでは、プロパティを使用してweakSelfとして参照しようとしました。これらをローカル変数に変更しましたが、まだリークしています。
何か案は?
元の質問
MKNetworkKit と Core Data を使用してプロジェクトを引き継ぎました。Leaks でプロジェクトを実行した後、アプリのさまざまな場所で多くのリークされたオブジェクトを確認できます。
コードをデバッグした後、リークしているオブジェクトは、MKNetworkKit リクエスト (setCompletionBlock:) のコールバックで発生している 2 つのフェッチ リクエストであることがわかります。データを挿入または更新する必要があるかどうかを確認するには、フェッチ要求を実行する必要があります。
いくつかの追加情報。完了ブロック内で、ManagedObjectContext のインスタンスを取得し、「NSPrivateQueueConcurrencyType」の同時実行タイプでそれを作成し、挿入を実行するために、モックで「performBlock:」を正しく呼び出しています。
お知らせ下さい。
ジェームズ
ブロックのサンプル コード: 注意: 2 つのフェッチ リクエストをコメントアウトしましたが、リークはなく、それらを元に戻すと、何百ものオブジェクトのリークが発生します。 )。
- (void) updateDbObjects: (int) page withCallback: (CompletionResultsNumberBlock) callback {
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
dispatch_queue_t callerQueue = dispatch_get_current_queue();
#pragma GCC diagnostic warning "-Wdeprecated-declarations"
__weak typeof(self) weakSelf = self;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[self createFullPath:urlStr]]];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSManagedObjectContext *moc = [weakSelf managedObjectContextForCurrentThread];
DataRoot *dataRoot = [DataRoot sharedInstanceInMoc:moc];
NSArray *returnJSON = JSON[@"object"];
__block int count = returnJSON.count;
if (!count)
{
dispatch_async(callerQueue, ^{
callback(0);
});
return;
}
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"DBObjects"];
NSError *error;
NSArray *allDBObjects = [moc executeFetchRequest:fetchRequest error:&error];
NSMutableDictionary *objectsById = [NSMutableDictionary dictionaryWithObjects:allTeamsArray forKeys:[allTeamsArray valueForKey: GoalTeamObjectAttributes.teamId]];
for (NSDictionary *rootDict in returnJSON)
{
GoalTeamObject *dbObject = objectsById[rootDict[@"id"]];
if (dbObject == nil)
{
dbObject = [DBObjects insertInManagedObjectContext:dataRoot.managedObjectContext];
}
[weakSelf importStandardParametersFrom:rootDict into:dbObject withPrefix:@""];
}
returnJSON = nil;
objectsById = nil;
[dataRoot saveContext];
NSError *childError = nil;
if ([moc save:&childError]) {
NSError *parentError = nil;
if (![moc.parentContext save:&parentError]) {
NSLog(@"Error saving parent");
}
dispatch_async(callerQueue, ^{
callback(count);
});
} else {
NSLog(@"Error saving child");
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
}];
[operation start];
}
このコードは次のように呼び出されます。多くのページのデータがあるため、ループ内で再帰的に呼び出されます。
__block int page = 1;
__weak typeof(self) weakSelf = self;
CompletionResultsNumberBlock loadData;
__block CompletionResultsNumberBlock block_loadData = loadData = ^(int results)
{
if (results < 100)
{
dispatch_async(callerQueue, callback);
} else {
[weakSelf updateDbObjects:++page withCallback:block_loadData];
}
};
[self updateDbObjects:page withCallback: loadData];