如何处理正在释放的ViewController,在关闭后面的线程后引用现在发布的ViewController?

时间:2012-05-18 07:06:39

标签: iphone objective-c ios uiviewcontroller sigabrt

我有一个ViewController被推送到NavigationController堆栈。一旦它被推入堆栈,它就会开始通过下载器对象下载一些图像,该对象负责在后台线程中下载图像。即使通过WiFi下载,图像也可能需要几秒钟。当图像下载完毕后,下载程序对象会指示ViewController布置其图像,将新下载的图像放在分页UIScrollView的后面。但是在此期间,用户可能已经按下了Back按钮,ViewController现在可能已被释放/解除分配,因此下载器对象将导致SIGABRT错误消息,应用程序将崩溃。

我该如何应对这种情况?有没有办法检查已发布/已释放的实例?或者某种方式来捕获错误并记录,然后忽略它呢?

3 个答案:

答案 0 :(得分:3)

您最好的选择是使用归零弱引用。当然,对于iOS 5.0,这只是一个“弱”的引用。但是,如果您的目标是iOS 5.0以下,那么您需要一个自定义解决方案。 Mike Ash在this文章中描述了一个很好的。

答案 1 :(得分:1)

也许你可以通过使用通知来避免这个问题?它不是引用viewController的下载器对象,而是发布一个通知,viewController(如果已加载)响应该通知。

数据加载对象中的

[[NSNotificationCenter defaultCenter] postNotificationName:@"allDataLoaded" object:nil];
视图控制器中的

viewDidLoad:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshMyLayout) name:@"allDataLoaded" object:nil];

在你的视图控制器dealloc中:

[[NSNotificationCenter defaultCenter] removeObserver:self];

你甚至可以在viewController的viewDidUnload中输入反向通知来告诉数据下载器取消下载(如果你想要的话)。

答案 2 :(得分:0)

最好的方法是在不再需要结果后取消下载。这可以防止不必要的数据流量和内存消耗。

如果你不能这样做,下载器对象应该有某种委托(可能是你的视图控制器),当你不再对结果感兴趣时你可以设置为nil(例如在你的查看控制器的dealloc方法)。如果您定位iOS 5,也可以选择将弱引用归零,但同样,取消下载NSURLConnection会更好。