5

编辑问题:21/10/2013 20:10 GMT

添加了如何在下面调用该方法,并且泄漏的对象是“allDBObjects”如果我删除它并将下面的字典更改为“NSMutableDictionary *objectsById”,则没有泄漏。

编辑问题:21/10/2013

几天没有讨论这个问题后,我又回来了。我相信这一切都归结为“释放问题”(https://developer.apple.com/library/ios/technotes/tn2109/_index.html#//apple_ref/doc/uid/DTS40010274-CH1-SUBSECTION11)。我已经使用 MKNetworkKit 和 AFNetworking 1.3.3 进行了测试(更改 1 方法以使用 AFNetworking 而不是 MKNetwork Kit)并且仍然在我的完成块中泄漏这些对象。我的块中没有对 self 的引用,并且使用 AFNetworking 我可以看到完成块设置为 nil,并且我尝试通过设置 [weakOp setCompletionBlock:nil] 手动中断保留周期。

编辑:下面的代码示例我尝试使用属性并将它们引用为weakSelf。我现在已将这些更改为局部变量,但它们仍然泄漏。

有任何想法吗?

原始问题

我接手了一个使用 MKNetworkKit 和 Core Data 的项目,在通过 Leaks in Instruments 运行项目后,我可以在应用程序的各个地方看到很多泄漏的对象。

调试代码后,我可以看到泄漏的对象是 MKNetworkKit 请求 (setCompletionBlock:) 的回调中发生的 2 个获取请求。需要执行获取请求以检查数据是否需要插入或更新。

一些进一步的信息。在完成块内,我得到了一个 ManagedObjectContext 实例,并使用并发类型“NSPrivateQueueConcurrencyType”创建它,并执行插入,我在 moc 上正确调用了“performBlock:”。

请指教。

詹姆士

块的示例代码:请注意:我已经注释掉了 2 个获取请求没有泄漏并将它们放回导致数百个对象的泄漏,我设置 NSDictionary 和 NSArray 的 weakSelf 属性是(非原子的,强)。

- (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

1

这看起来不对:

__block CompletionResultsNumberBlock block_loadData = loadData = ^...

在 ARC 下,该块将对其自身进行强引用。在 ARC 下,您应该这样做:

__block __weak CompletionResultsNumberBlock block_loadData = loadData = ^...
于 2013-10-23T06:15:06.427 回答
0

weakSelf在块内的某些地方和self其他地方使用。这意味着该块仍将self以强大的方式捕获。

我会先尝试在您的块中替换所有self对with的引用。weakSelf

于 2013-10-21T16:44:07.917 回答