2011-07-28 163 views
3

已解决(我认为):设置ASIHTTPRequest委托/ NSOperationQueue委托在vc弹出后(在dealloc中)为零。ASIHTTPRequest和僵尸...

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

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


开始的问题:

基本上,当ASIHTTPRequest试图调用的requestFinished选择器,到一个对象,它是一个僵尸发生这种错误。

从环顾四周,看起来ASIHTTPRequest在向僵尸发送选择器时会将它发送给一个不是僵尸的类似对象。我听说它将选择器发送给它要发送给它的控制器的CALayer是非常常见的,并且还将它发送给我的UINavigationButton!?无论如何,这样做的效果是它会抛出异常。

问题发生ASIHTTPRequest类的内部时,它试图将“requestFinished”选择拨打:

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

这行代码是一个失败的 - 令我百思不解的是为什么呢?在我所链接的问题上,OP表示他们通过从视图控制器调用[self retain]来修复它。当然,这是不正确的?

结构

的方式我ASIHTTPRequest的工作,是他们被添加到downloadQueue,(NSOperationQueue),它位于我的应用程序委托中。我的应用程序的结构/风格主要基于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 

  • 感谢如果你读到这里!如果你回答
  • 赏金,如果你解决我的问题:)

回答

6

如果您输入详细信息视图,进度栏开始移动,并且您再次弹出到根目录,则通常会发生这种情况。这使我相信,因为控制器不活动,当ASIHTTPRequest完成时,它试图调用控制器,它失败。

我认为你对此正确。

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

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

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

+0

嗨,没关系,我可以简单地清除请求,因为每个网络摄像头都使用相同的细节控制器,所以尝试保存请求将毫无意义。无论如何,你如何检测流行(不只是viewWillDisappear)... –

+0

我不明白,如果你可以取消请求,无论如何我编辑我的答案,添加有关检测流行的信息... – sergio

+0

对不起,我的意思是通过'甩垃圾请求'去除代表团 –

0

你不应该在现场的应用程序使用NSZombieEnabled

  • 感谢甚至更多,内存是永远不会释放。您在开发时需要关闭它。快速推拉可能会耗尽记忆,引发记忆警告,并导致事情被释放和释放。直到您发布崩溃日志之前,我们不会确定。

  • +0

    我只通过仪器测试过僵尸......我只是使用术语僵尸来指称过度释放的对象。现在将发布崩溃日志。 –

    0

    以下是我解决了这个问题:在你的viewController的dealloc方法设置任何优秀ASIHTTPRequest S的delegatenil

    这从将消息发送到didFinishSelector S,小号等上的viewController所述的viewController被弹出后从导航堆栈和dealloc“d防止优秀ASIHTTPRequest秒。

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