ASIHTTPRequest导致我的应用程序崩溃

9
我有一个基于导航的应用程序。在主视图上按下一个按钮,然后我向导航控制器推送一个新视图。这些都是相当基础的东西。
当加载新视图时,我执行ASIHTTPRequest以获取一些JSON数据,其中包含图像URL列表。 然后我进行for循环,创建一堆ASIHTTPRequests,将它们添加到队列中,然后运行队列。
但是,如果在队列完成之前点击返回按钮,应用程序会崩溃。该应用程序显示房屋,并且假设您选择了错误的房屋,快速点击返回按钮,而没有显示任何照片,就会崩溃。
这个线程http://groups.google.com/group/asihttprequest/browse_thread/thread/3d4815198aa889b9很好地解释了我的问题,除了我在视图取消加载时取消所有请求,将委托设置为nil并释放队列。
即使如此,我仍然会崩溃。如果使用3G,我几乎每次都会崩溃,但在WiFi上很难让它崩溃,但是完全可以做到。
在近80%的情况下,调试器会跳转到ASIHTTPRequest.m中的这一行。
(void)requestReceivedResponseHeaders:(NSMutableDictionary *)newResponseHeaders { 
  if ([self error] || [self mainRequest]) { return; }  
--> if (delegate && [delegate respondsToSelector:didReceiveResponseHeadersSelector]) {

许多情况下它会跳转到:
(void)requestReceivedResponseHeaders:(NSMutableDictionary *)newResponseHeaders { 
  if ([self error] || [self mainRequest]) { return; }    
---> if (delegate && [delegate respondsToSelector:didReceiveResponseHeadersSelector]) {  

在一些情况下,它会进入我的主循环。
int main(int argc, char *argv[]) {  
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
--> int retVal = UIApplicationMain(argc, argv, nil, nil); with SIGBART error [pool release]; return retVal;  

我正在使用MBP和MacPro,最新的OS X,Xcode 4.0.2,并在除原始iPhone之外的所有苹果设备上进行测试。
我真的不想重新编写我的整个应用程序,但是否有其他与ASIHTTPRequest相似的东西?
4个回答

12

尝试在-viewWillUnload中取消和取消设置委托,而不是在-viewDidUnload中。我怀疑实际卸载的时间窗口(在调用这两个UIViewController方法之间)是您可能会崩溃的时间段。委托已经消失了,但您还没有告诉您的ASIHTTPRequest对象。


6
在viewWillDissapear方法中,似乎已经解决了问题,至少我无法再使其崩溃。但是,我还添加了以下代码,以确保:- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; for (ASIHTTPRequest *req in [queue operations]) { [req clearDelegatesAndCancel]; [req setDelegate:nil]; [req setDidFailSelector:nil]; [req setDidFinishSelector:nil]; } [queue cancelAllOperations]; [queue setDelegate:nil]; } - Trausti Thor

4
错误在于委托仍然被设置。我找到了两种解决方法。我认为不好看的方法是创建一个通用委托,处理所有网络流量,并在应用首次运行时实例化。我实际上使用了应用委托并侦听NSNotification中心消息。它非常有效,应用程序从未崩溃,但我认为这不是最佳选择。 最好的方法是不设置委托,也不使用"setDidFinishSelector",而是使用"setCompletionBlock:^"。这只能在运行iOS 4.0及更高版本的设备上使用,这已经超过90-95%并持续增长。这是一种非常棒的方法,不会使应用程序崩溃。

使用第二种方法确实可行。谢谢。我被卡住了太久了。干杯。 - try catch finally

3
您不会找到比ASIHTTPRequest更好的东西,问题在于您如何使用它,并且导航时消失委托是一个常见的问题需要处理。
听起来您的问题与正在处理队列的视图控制器由于用户导航而被销毁有关。我发现解决这些问题的最佳方法是拥有一个中央模型类,该类处理所有通信并在整个应用程序生命周期内保持该类。
这样,当委托突然消失时,您就不会遇到无法解释的崩溃。
另一种方法可以是禁用用户导航直到网络操作完成。在整个屏幕上放置一个模态视图,显示一个uiactivityview,以便用户知道他们的操作正在被阻止。然后,当数据到达时,您可以淡化模态视图。如果您将屏幕设计得很好,具有渐变效果,使背景略微变暗,这看起来可能还不错。但这不是最好的方法-您应该修复代表AWOL。
我们可能需要查看更多与队列创建,销毁等相关的代码,以找到确切的问题。

这样的中心类会是什么样子? - Trausti Thor
我认为一个中央类将是一个单例。 - Tuyen Nguyen
可以是单例对象,也可以是只被应用程序委托实例化一次并保留的类。 - Roger

1

你的应用程序代理可以拥有一个请求队列数组。该数组独立于导航控制器堆栈和相关视图的状态之外。不要将请求与导航堆栈中的视图控制器绑定,并且不必使用UI技巧来阻止返回到父视图,而是可以将请求添加到应用程序代理队列实例中,或停止所有请求并清空队列等。


你能解释一下如何创建一个单例委托,或者我应该只使用 App 委托?你的想法听起来很有趣,但我还无法完全想象它。 - Trausti Thor
只需使用应用程序委托即可。或者您可以创建一个由应用程序委托拥有的单例。您可以在SO上搜索“cocoa singleton”以获取更多信息。 - Alex Reynolds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接