可达性类崩溃程序 – 不知道为什么

我有一个“互联网意识”基础类的对象,需要在我的应用程序networking。 所有需要互联网识别的对象都从中inheritance。 正如你可以想象的,我分配和释放了很多这些对象。

互联网意识的基类具有以下代码来与用于检查互联网状态的可访问性类进行交互。

#import "Reachability.h" - (id) init { ... self.internetReachable = [Reachability reachabilityForInternetConnection]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkNetworkStatus) name:kReachabilityChangedNotification object:nil]; [self.internetReachable startNotifier]; ... } - (void) dealloc { [self.internetReachable stopNotifier]; [[NSNotificationCenter defaultCenter] removeObserver:self]; } 

一旦在我的应用程序的互联网状态发生变化,应用程序崩溃,出现以下错误:

*** – [Reachability isKindOfClass:]:发送到释放实例0x1e249a30的消息

我打开了僵尸,并将问题追溯到Reachability.m中的以下代码行

 NSCAssert([(NSObject*) info isKindOfClass: [Reachability class]], @"info was wrong class in ReachabilityCallback"); 

不幸的是,除了停止听取NSNotifcations和停止通知程序,我不知道还有什么我的对象可以做,以避免这个错误。

任何帮助或build议将是伟大的。

谢谢

VB

编辑:

好,所以按照下面的答案的build议我用分配仪器运行它,这是保留计数的历史。

在这里输入图像说明

正如我所怀疑的那样,我已经释放的一个对象被基金会(即NSNotifcationCenter)所调用,而不是我自己。

我的互联网对象有一个指向Reachability对象的强指针。 当它们被释放时,Reachability对象也是如此。 僵尸是Reachability对象。 在我的互联网对象的dealloc中,我调用了removeObserver,但是基础仍然在调用deallocated对象。 我不明白为什么…

NSCAssert行是您第一次访问释放对象的地方,但是如果您想了解对象的生命周期的更多信息,您应该使用Instruments。 使用Xcode的configuration文件工具,在仿真器中使用Allocations(但不泄漏!)工具运行程序。 在分配工具的启动configuration中打开启用NSZombie检测logging引用计数。 当你击中NSCAssert线时,仪器应该检测到消息僵尸信息对象的消息并logging下来。 如果您查看僵尸信息对象的详细信息,仪器将显示其引用计数的历史logging,您应该能够看到何时解除分配。

基金会仍然在发送释放可达性NSNotifcations的原因是因为Reachability对象被释放在一个不同的线程上它正在创build一个。 可达性不是线程安全的。 使用dispatch_async回到正在创buildReachability对象的队列已经解决了这个问题。

发生这种情况时,你实例化可达性的对象,因此持有一个可达性实例的引用,释放没有(或之前)你调用stopNotifier!

解决这个问题非常简单。 您必须先调用stopNotifier才能将对象从堆栈中移除,并使用它撕毁您的Reachability实例。 你可以在dealloc方法中做到这一点,或者如果它是一个viewController,你可以在其中一个生命周期方法,如viewDidDisappear等调用它。

这里不需要搞乱线程。 考虑一下,当你在Reachability上调用startNotifier时,这个事情在Reachability的devise背景线程上开始。 所以,当你打电话给stopNotifier时,它会帮你处理线程。

你不得不惹恼线程的原因是你的对象持有对Reachability的引用已经被释放,但仍然是一个networking变化的注册监听者,这在startNotifier中发生了。 当networking发生变化时,猜测你的对象,虽然仍然注册接收通知,但却无处可寻! 崩溃的崩溃。 stopNotifier在它死亡之前取消注册,一切都很好。

 - (void)dealloc { // self.hostReachability is my property holding my Reachability instance if (self.hostReachability) { [self.hostReachability stopNotifier]; } }