ASIHTTPRequest和Zombies ......

时间:2011-07-28 20:07:43

标签: iphone ios debugging asihttprequest nszombie

已解决(我认为):在弹出vc后(在dealloc中)将ASIHTTPRequest委托/ NSOperationQueue委托设置为nil。

在开始之前,this问题类似但不一样。

我的应用程序非常接近发布,但这是整个开发过程中存在的唯一持久性错误。它也是向某人演示应用程序时发生的唯一错误,并且由于此错误导致应用程序终止,因此非常令人尴尬。如果有人能找到解决方案(好的),我会奖励一个体面的奖金。


问题开始:

基本上,当ASIHTTPRequest尝试将requestFinished选择器调用到一个僵尸对象上时会发生此错误。

从环顾四周看,ASIHTTPRequest在面对向僵尸发送选择器时,会将其发送给不是僵尸的类似对象。我听说让它将选择器发送到它本发送给它的控制器的CALayer是很常见的,而且我也把它发送到我的UINavigationButton !? - 无论如何,这会产生异常。

当ASIHTTPRequest类尝试调用'requestFinished'选择器时,会出现问题:

[queue performSelector:@selector(requestFinished:) withObject:self];

这行代码就是失败的代码 - 让我感到困惑的是为什么?在我链接的问题上,OP表示他们通过从视图控制器调用[self retain]来修复它。当然那不对吗?

结构

我的ASIHTTPRequest的工作方式是,它们被添加到downloadQueue,(NSOperationQueue),它位于我的app委托中。我的应用程序的结构/样式主要基于this sample code,它使用flickr RSS提要做了类似的事情。

我的应用使用ASIHTTPRequest的部分是一个网络摄像头查看器。它有一个带有桌面视图的导航控制器,可显示三个网络摄像头。这些图像是JPEG,每30秒更新一次到静态文件(在远程服务器上)。此表视图中的单元格是自定义的,每个单元格都加载自己的ASIHTTPRequest。单元格下载各自的图像,并显示它们。

这是我创建的方法,在我的每个单元格上调用:

- (void)loadURL:(NSURL *)url {
    ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:url];
    [request setDelegate:self];
    [request setDidFinishSelector:@selector(requestDone:)];
    [request setDidFailSelector:@selector(requestWentWrong:)];
    NSOperationQueue *queue = [[MyAppDelegate sharedAppDelegate] downloadQueue];
    [queue addOperation:request];
    [spinner startAnimating];
    [self addSubview:spinner];
    [request release];  
}

当选择其中一个单元格时,它会将用户带到详细视图,其中加载了另一个ASIHTTPRequest实例,该实例将下载所选网络摄像头的图像。

如何触发错误

在我的应用程序的正常“平静”使用情况下,它表现良好。在这些视图之间(根网络和详细网络摄像头视图之间)发生快速推送和弹出时,会出现此问题。 最常见的情况是,如果您输入详细视图,进度条开始移动,然后再次弹出到根。这使我相信,因为控制器未激活,当ASIHTTPRequest完成时,并且它试图调用控制器,它失败了。

崩溃日志

Exception Type:  EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x00000480
Crashed Thread:  0

Thread 0 Crashed:
0   libobjc.A.dylib                 0x30183f24 objc_msgSend + 24
1   iCompton                        0x0003c4d4 0x1000 + 242900
2   CoreFoundation                  0x35ea3f72 -[NSObject(NSObject) performSelector:withObject:] + 18
3   iCompton                        0x00029082 0x1000 + 163970
4   CoreFoundation                  0x35ea3f72 -[NSObject(NSObject) performSelector:withObject:] + 18
5   Foundation                      0x33fd3e66 __NSThreadPerformPerform + 266
6   CoreFoundation                  0x35ebc8ca __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 8
7   CoreFoundation                  0x35e8cec6 __CFRunLoopDoSources0 + 378
8   CoreFoundation                  0x35e8c6f2 __CFRunLoopRun + 258
9   CoreFoundation                  0x35e8c504 CFRunLoopRunSpecific + 220
10  CoreFoundation                  0x35e8c412 CFRunLoopRunInMode + 54
11  GraphicsServices                0x35261d1c GSEventRunModal + 188
12  UIKit                           0x33865574 -[UIApplication _run] + 580
13  UIKit                           0x33862550 UIApplicationMain + 964
14  iCompton                        0x00002b92 0x1000 + 7058
15  iCompton                        0x00002b44 0x1000 + 6980

  • 谢谢你,如果你读到这里远!
  • 如果你回答
  • ,甚至还要多谢
  • 赏金,如果你解决了我的问题:)

3 个答案:

答案 0 :(得分:6)

  

最常见的情况是,如果您输入详细视图,进度条开始移动,并再次弹出到根目录。这让我相信,因为控制器不活动,当ASIHTTPRequest完成,并且它试图调用控制器时,它会失败。

我认为你是正确的。

当您弹出到根控制器(或任何其他控制器)时,您应该尝试取消ASIHTTPRequest。在取消请求之前,您应将其delegate设置为nil;或者你可以使用clearDelegatesAndCancel

可能这需要您在视图控制器中保留对请求的引用,但这应该没问题。

一个有趣的S.O.关于检测弹出的UIViewController的问题/答案是here

答案 1 :(得分:0)

你不应该在实时应用程序中使用NSZombieEnabled,内存永远不会被释放。你不需要在开发中关闭它。快速推拉可能会耗尽内存,触发内存警告,并导致事物被释放和释放。在发布崩溃日志之前,我们不会确切知道。

答案 2 :(得分:0)

以下是我解决此问题的方法:在viewController的delegate方法中将ASIHTTPRequest的{​​{1}} nil设置为dealloc

这阻止了杰出的ASIHTTPRequest在viewController从导航堆栈弹出后didFinishSelector向viewController上的didFailSelectordealloc等发送消息“d。

请注意:ASIHTTPRequest方法cancelAllOperations 可能异步调用didFailSelector。在这种情况下,可以在不再存在的viewController上调用选择器