我正在尝试从另一个completionHandler块内部调用'completionHandler'块(在异步URL请求之后调用)。但是这会导致应用程序崩溃并显示以下消息(我正在使用Zombie对象):
*** -[CFRunLoopTimer hash]: message sent to deallocated instance
使用仪器我能够发现问题是由于块被解除分配但我无法弄清楚如何保持它足够长的时间。是因为我从另一个异步块调用块吗?我的代码如下(MyCompletionHandler返回void
并接受void
):
-(void)requestWithRequest:(NSURLRequest*)request withCompletionHandler:(MyCompletionHandler)serverCompletionHandler{
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// do stuff…
if (serverCompletionHandler) {
dispatch_async(dispatch_get_main_queue(), ^{
serverCompletionHandler();
});
}];
}
但是这个代码是通过另一个提供serverCompletionHandler
参数的方法调用的(这可能是问题吗?)。
例如,上述方法将通过此方法调用:
-(void)createAndSendRequestWithCompletionHandler:(MyCompletionHandler)serverCompletionHandler{
NSMutableURLRequest* request = //..
[self requestWithRequest:request withCompletionHandler:serverCompletionHandler];
}
仪器显示一个块被释放或删除(我假设我正在调用的块),这将解释被调用的释放对象。
任何帮助都将不胜感激。
修改
计时器的代码(似乎已取消分配)是:
if ([timer isValid]) {
[timer invalidate];
}
timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(createAndSendRequestWithCompletionHandler:) userInfo:nil repeats:YES];
令人困惑的是代码工作正常,直到我添加了completionHandler
s。
答案 0 :(得分:2)
这不是一个问题,你可以在另一个区块中访问该区块。我认为问题是你已经在mainQueue([NSOperationQueue mainQueue]
)上了,你再次尝试在mainQueue上getMainQueue
。{{{ 1}}使用队列的sendAsynchronousRequest
,当你再次请求主队列时,它会被释放。因为你已经在主队列上了。你可以检查你是否已经在主队列上,只需要调用NSRunloop
else {{1在这种情况下,您可以跳过此检查,因为您确定自己为serverCompletionHandler
并且可以致电dispatch on mainqueue
main queue
编辑:感谢编辑过的代码。正在使用
serverCompletionHandler()
现在,由于您未通过[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
// do stuff…
if([[NSOperationQueue currentQueue] isEqual:[NSOperationQueue mainQueue]]){ //check for main queue
if (serverCompletionHandler) {
serverCompletionHandler();
}
}
else{
if (serverCompletionHandler) { if not than dispatch on main queue
dispatch_async(dispatch_get_main_queue(), ^{ //No need to do that
serverCompletionHandler();
});
}
}];
,因此timer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(createAndSendRequestWithCompletionHandler:) userInfo:nil repeats:YES];
计时器将自己传递给completionhandler
。
因此createAndSendRequestWithCompletionHandler:
本身包含serverCompletionHandler
个对象,而不包含任何serverCompletionHandler
个对象。如果您在timer
中尝试block
NSLog
,您会发现它是计时器对象。现在,当dispatch_async尝试调用serverCompletionHandler
因为它没有阻塞时,它将崩溃。
在requestWithRequest
serverCompletionHandler
编辑2
如果你真的想传递完成处理程序而不是传递计时器对象的createAndSendRequestWithCompletionHandler
。使用下面的代码
NSLog(@"serverCompletionHandler obnj %@",serverCompletionHandler );
NSLog(@"class %@",NSStringFromClass([serverCompletionHandler class] ));