【发布时间】:2013-10-15 08:51:20
【问题描述】:
编辑问题: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 我可以看到 completionBlock 设置为 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];
【问题讨论】:
-
你能显示完成块的来源吗?
-
你可以贴一些代码吗?
-
@jodm:
weakOp是如何定义的? -
添加了如何在上面的代码中定义weakOp。还添加了缺少的 DataRoot 类。
-
1) 可能是分析器错误。但是,这几乎是不可能的 2) 你确定泄漏的对象是 NSFetchRequests 吗?评论它们并消除泄漏并不意味着它们正在泄漏。 3) 你的代码对我来说一切都很好,要么是魔法,要么是信息不足。
标签: ios objective-c memory-leaks objective-c-blocks nsoperationqueue