CoreLocation线程崩溃崩溃:com.apple.CoreLocation.ConnectionClient.0x16fcb870.events

我在生产应用程序的Apple CoreLocation线程中遇到了这个崩溃。 我不能在我的testing中重现它,也很难弄清楚它是否在CoreLocation中。 目前发生的人口比例很低,但我可以看到它变得越来越大。

Crashed: com.apple.CoreLocation.ConnectionClient.0x16fcb870.events 0 CoreLocation 0x2aa2db54 CLClientCreateIso6709Notation + 53675 1 CoreLocation 0x2aa2dc7b CLClientCreateIso6709Notation + 53970 2 CoreLocation 0x2aa2de03 CLClientCreateIso6709Notation + 54362 3 CoreLocation 0x2aa2dcfb CLClientCreateIso6709Notation + 54098 4 CoreLocation 0x2aa30f59 CLClientCreateIso6709Notation + 66992 5 CoreLocation 0x2aa31089 CLClientCreateIso6709Notation + 67296 6 CoreFoundation 0x24954699 <redacted> + 16 7 CoreFoundation 0x2493f698 <redacted> + 120 8 CoreFoundation 0x24948575 CFDictionaryApplyFunction + 172 9 CoreLocation 0x2aa3036d CLClientCreateIso6709Notation + 63940 10 CoreLocation 0x2aa2edaf CLClientCreateIso6709Notation + 58374 11 libxpc.dylib 0x247816e5 <redacted> + 40 12 libxpc.dylib 0x24784413 <redacted> + 122 13 libxpc.dylib 0x2478436d <redacted> + 48 14 libxpc.dylib 0x24784319 <redacted> + 64 15 libxpc.dylib 0x2477fbb9 <redacted> + 1512 16 libdispatch.dylib 0x245c75a1 <redacted> + 516 17 libdispatch.dylib 0x245cd9ed <redacted> + 592 18 libdispatch.dylib 0x245c689b <redacted> + 362 19 libdispatch.dylib 0x245cd9ed <redacted> + 592 20 libdispatch.dylib 0x245c6e17 <redacted> + 282 21 libdispatch.dylib 0x245cd9ed <redacted> + 592 22 libdispatch.dylib 0x245c6e17 <redacted> + 282 23 libdispatch.dylib 0x245cf20d <redacted> + 400 24 libdispatch.dylib 0x245cf07b <redacted> + 94 25 libsystem_pthread.dylib 0x24762e0d _pthread_wqthread + 1024 26 libsystem_pthread.dylib 0x247629fc start_wqthread + 8 

我们正在使用CoreLocation来监视和范围特定的信标区域,这里是查找附近信标的代码。 另外请注意, HPBeaconManager在应用程序到达前台时HPBeaconManager初始化,而从crashlytics报告看起来应用程序到达前台时会发生这种情况。 破坏CLLocationManger对象和重新初始化是否会导致此问题? 任何正确的方向导向将不胜感激。

这是调用代码。

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { self.beaconManager = HPBeaconManager() self.beaconManager?.startMonitoring() return true; } func applicationDidBecomeActive(application: UIApplication) if (( self.beaconManager ) != nil){ self.beaconManager = nil; } self.beaconManager = HPBeaconManager() self.beaconManager?.startRanging() } 

这是HPBeaconManager的实现。

 class HPBeaconManager: NSObject , CLLocationManagerDelegate { var propertyBeaconRegion: HPBeaconRegion? var agentBeaconRegion: HPBeaconRegion? var locationManager: CLLocationManager = CLLocationManager() var delegate:BeaconManagerDelegate? var beacons:NSMutableSet = NSMutableSet() override init() { super.init() self.propertyBeaconRegion = HPBeaconRegion(proximityUUID: HPBeaconCommons.propertyUUID, major: CLBeaconMajorValue(1), identifier: HPBeaconCommons.propertyBeaconIdentifier) self.agentBeaconRegion = HPBeaconRegion(proximityUUID: HPBeaconCommons.agentUUID, major: CLBeaconMajorValue(1), identifier: HPBeaconCommons.agentBeaconIdentifier) self.locationManager = CLLocationManager() self.locationManager.delegate = self } func startMonitoring() -> Void { self.locationManager.startMonitoringForRegion(self.agentBeaconRegion!) self.locationManager.startMonitoringForRegion(self.propertyBeaconRegion!) self.locationManager.startRangingBeaconsInRegion(self.agentBeaconRegion!) self.locationManager.startRangingBeaconsInRegion(self.propertyBeaconRegion!) strongSelf.locationManager.startUpdatingLocation() } func stopMonitoring() -> Void { self.locationManager.stopMonitoringForRegion(self.agentBeaconRegion!) self.locationManager.stopMonitoringForRegion(self.propertyBeaconRegion!) self.locationManager.stopRangingBeaconsInRegion(self.agentBeaconRegion!) self.locationManager.stopRangingBeaconsInRegion(self.propertyBeaconRegion!) self.locationManager.stopUpdatingLocation() } func startRanging() { self.locationManager.startRangingBeaconsInRegion(self.agentBeaconRegion!) self.locationManager.startRangingBeaconsInRegion(self.propertyBeaconRegion!) } func locationManager(manager: CLLocationManager, didStartMonitoringForRegion region: CLRegion) { NSLog("\n ************** Monitoring starts for region %@", region.identifier) } func locationManager(manager: CLLocationManager, didDetermineState state: CLRegionState, forRegion region: CLRegion) { } func locationManager(manager: CLLocationManager, didEnterRegion region: CLRegion) { NSLog("\n ************** Did Enter Region") } func locationManager(manager: CLLocationManager, didExitRegion region: CLRegion) { } func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) { var locationArray = locations as NSArray if locationArray.count > 0 { var locationObj = locationArray.lastObject as! CLLocation var coord = locationObj.coordinate let loationString = "\(coord.latitude)|\(coord.longitude)" } } func locationManager(manager: CLLocationManager!, didRangeBeacons beacons: [AnyObject]!, inRegion region: CLBeaconRegion!) { if beacons.count > 0 { let nearestBeacon:CLBeacon = beacons[0] as! CLBeacon .... } } func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) { if status == .AuthorizedAlways { NSLog("Location Access (Always) granted!") dispatch_after(dispatch_time_t(0.5), dispatch_get_main_queue(), { [weak self] in if let strongSelf = self { if manager.rangedRegions.isEmpty { NSLog("Ranged region is empty") } strongSelf.startMonitoring() } }) } else if status == .AuthorizedWhenInUse { NSLog("Location Access (When In Use) granted!") dispatch_after(dispatch_time_t(0.5), dispatch_get_main_queue(), { [weak self] in if let strongSelf = self { if manager.rangedRegions.isEmpty { NSLog("Ranged region is empty") } strongSelf.startMonitoring() } }) } else if status == .Denied || status == .Restricted { NSLog("Location Access (When In Use) denied!") } } deinit { NSLog("BeaconManager cleanup") self.locationManager.stopUpdatingLocation() self.locationManager.delegate = nil } } 

虽然这并不明显,这将导致崩溃, CLBeaconManagerapplicationDidBecomeActive启动的方式可能会导致问题。

每当应用程序到达前台时, HPBeaconManager构build一个新的HPBeaconManager ,创build一个新的CLLocationManager对象。 旧的HPBeaconManager被取消引用,导致ARC将垃圾收集并在稍后将其销毁,届时将deinit()方法,并将第一个locationManager的委托设置为nil。 在这种情况下,在新的HPBeaconManager处于活动状态的同时,仍然会在旧的HPBeaconManager上调用委托方法。

理论上这一切都应该工作。 但是,根据ARC清理旧的HPBeaconManagerCLLocationManager实例需要多长时间,用户将应用程序前后移动到最前面的用户可能会同时处于活动状态。 如果这造成了微妙的错误,可能会导致CoreLocation的内部崩溃,这并不会让我感到惊讶。

我build议重构HPBeaconManager以便在应用程序到达前台时根据需要重新初始化它,而无需创build新的对象实例。 避免此对象stream失可能会使应用程序更稳定。