3

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

在我开始之前,这个问题是相似的,但又不一样。

我的应用程序即将发布,但这是整个开发过程中唯一存在的持久性错误。这也是向某人演示应用程序时出现的唯一错误,并且由于此错误导致应用程序终止,因此非常尴尬。如果有人能找到解决这个问题(永远),我将奖励一个体面的赏金。


问题开始:

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

环顾四周,似乎 ASIHTTPRequest 在面对将选择器发送给僵尸时,会将其发送给不是僵尸的类似对象。我听说将选择器发送到它要发送到的控制器的 CALayer 是很常见的,而且我也将它发送到我的 UINavigationButton!?- 无论如何,这样做的效果是它抛出了一个异常。

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

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

那行代码是它失败的那一行 - 令我困惑的是为什么?在我链接到的问题上,OP 说他们通过[self retain]从视图控制器调用来修复它。这肯定不对吧?

结构

我的 ASIHTTPRequest 的工作方式是将它们添加到位于我的应用程序委托中的下载队列 (NSOperationQueue)。我的应用程序的结构/样式主要基于此示例代码,它做了非常相似的事情,但使用了 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];  
}

When one of these cells is selected, it takes the user to a detail view, where another instance of ASIHTTPRequest is loaded, which downloads the image for the selected webcam.

错误是如何触发的

在我的应用程序的正常“平静”使用下,它表现良好。当这些视图之间(根和详细网络摄像头视图之间)发生快速推送和弹出时,就会出现问题。如果您进入详细视图,进度条开始移动,并且您再次弹出到根目录,则通常会发生这种情况。这让我相信,由于控制器未处于活动状态,因此当 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

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

3 回答 3

6

如果您进入详细视图,进度条开始移动,并且您再次弹出到根目录,则通常会发生这种情况。这让我相信,由于控制器未处于活动状态,因此当 ASIHTTPRequest 完成并尝试调用控制器时,它会失败。

我认为你在这方面是正确的。

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

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

关于检测 UIViewController 被弹出的一个有趣的 SO 问题/答案在这里

于 2011-07-28T20:50:01.093 回答
0

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

于 2011-07-28T20:11:58.563 回答
0

以下是我解决这个问题的方法:在 viewController 的方法 中设置delegate任何未完成ASIHTTPRequest的 s 为。nildealloc

这阻止了未完成ASIHTTPRequest的 sdidFinishSelectordidFailSelectorvi​​ewController 从导航堆栈中弹出并dealloc'd.

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

于 2011-08-25T20:54:48.500 回答