CLLocationManger 向分配的实例发送消息

Posted

技术标签:

【中文标题】CLLocationManger 向分配的实例发送消息【英文标题】:CLLocationManger sending message to dallocated instance 【发布时间】:2010-12-07 20:36:49 【问题描述】:

所以我有一个导航控制器,我在上面推了一个视图控制器,然后是第二个。在第二个中,我开始列出位置更新。好吧好吧。

当我点击第二个视图控制器上的后退按钮时,我有时会收到"*** -[DistanceScreen respondsToSelector:]: message sent to deallocated instance 0x1152a0" 注意在实际设备上进行测试(iPhone 4、4.2 ios)。

堆栈看起来像:

#0  0x33a69910 in ___forwarding___
#1  0x33a69860 in __forwarding_prep_0___
#2  0x343713fa in -[CLLocationManager onClientEventLocation:]
#3  0x3436f694 in -[CLLocationManager onClientEvent:supportInfo:]
#4  0x3436f80a in OnClientEvent
#5  0x3436b528 in CLClientInvokeCallback
#6  0x3436d3d2 in CLClientHandleDaemonDataLocation
#7  0x3436d518 in CLClientHandleDaemonData
#8  0x33a81404 in __CFMessagePortPerform
#9  0x33a556fe in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
#10 0x33a556c2 in __CFRunLoopDoSource1
#11 0x33a47f7c in __CFRunLoopRun
#12 0x33a47c86 in CFRunLoopRunSpecific
#13 0x33a47b8e in CFRunLoopRunInMode
#14 0x33b0e4aa in GSEventRunModal
#15 0x33b0e556 in GSEventRun
#16 0x32099328 in -[UIApplication _run]
#17 0x32096e92 in UIApplicationMain
#18 0x0000280e in main at main.m:13

上面的“DistanceScreen”是开始监听位置更新的视图控制器。在你回复之前,这里是 DistanceScreen 的 dealloc:

NSLog(@"DistanceScreen dealloc");
[locationManager setDelegate:nil];  
[locationManager stopUpdatingLocation];
[locationManager release];
//etc.
[super dealloc];

如果我将代理设置为 nil,为什么位置管理器看起来仍在尝试发送更新?还是因为 CLLocationManager 在自己的线程中做事,并在委托被释放时开始了位置更新过程????在这种情况下,没有简单安全的方法来停止侦听更新。

【问题讨论】:

好的,我可能已经在这里回答了我自己的问题。看起来我正在泄漏 CLLocationManager 实例,因为我正在这样做: self.locationManager=[CLLocationManager alloc] init];其中 locationManager 是保留属性。 我很确定静态分析器不会检查那些东西,但我会把它放回去试试。似乎任何时候我们都有一个保留的属性,然后执行 self.anyProp=[[AnyClass alloc] init];它应该被标记为问题。 即使你泄露了locationManager,你在dealloc之前已经将它的delegate设置为nil。那么,为什么您在调用代理时看到了崩溃? 【参考方案1】:

我在 4.3 上测试我的应用时遇到了同样的问题,但在 5.0 中没有。问题是我试图在委托方法之一中释放 CLLocationManager。它在 5.0 中运行良好,但每次运行 4.3 的 iPhone 3GS 都会崩溃。

最后我将 CLLocationManager 对象设置为一个属性,然后在委托方法中将委托设置为 nil 并分派一个块到主线程以释放该对象。

【讨论】:

是的。同样在这里。我只需要在委托的 dealloc 方法中释放位置管理器。为了防止崩溃。 当我们在没有开启定位服务的情况下在 iOS 4 上启动(构建但不运行)、停止应用程序、然后打开它们并再次运行时,就会发生这种崩溃。你的修复工作。 [经理 performSelectorOnMainThread:@selector(release) withObject:nil];被使用而不是自己释放,似乎不会崩溃。 Repro 确实很烦人,只会出现在新的设备构建中【参考方案2】:

我遇到了同样的问题,这篇文章帮助了我https://***.com/a/5214608/1210822

通过在 dealloc 中添加 self.locationManager.delegate = nil;。崩溃似乎已修复。

希望对你有帮助!

【讨论】:

以上是关于CLLocationManger 向分配的实例发送消息的主要内容,如果未能解决你的问题,请参考以下文章

alertView:didDismissWithButtonIndex: 消息发送到解除分配的实例

XCode App 随机崩溃 - 消息发送到解除分配的实例

仅使用实例角色从 Java 应用程序向 SES 发送邮件

如何从 index.html 向 Vue.js 3 实例发送消息?

SAML 2.0 实例分析 idp向sp发送响应

PGA结构