5

質問への編集: 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];
4

2 に答える 2

0

weakSelfブロック内のいくつかの場所で使用し、他の場所で使用しselfます。つまり、ブロックは引き続きself強力にキャプチャされます。

最初にブロック内のすべての参照をself置き換えてみます。weakSelf

于 2013-10-21T16:44:07.917 に答える