我在我们的生产应用程序的 Apple 的 CoreLocation 线程中遇到了这个崩溃。我无法在我的测试中重现它,也很难弄清楚它的内部 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 在 App 进入前台时重新初始化,并且来自 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,并创建一个新的 CLLocationManager 对象。旧的 HPBeaconManager 被取消引用,导致 ARC 对其进行垃圾收集并在稍后销毁它,届时将调用 deinit() 方法并且第一个 locationManager 的委托(delegate)设置为 nil。在此之前,仍将在旧 HPBeaconManager 上调用委托(delegate)方法,同时新 HPBeaconManager 处于事件状态。

从理论上讲,这一切都应该有效。但是,根据 ARC 清理旧的 HPBeaconManagerCLLocationManager 实例所需的时间,用户将应用程序来回切换到前台可能最终会同时激活多个实例。如果这会产生可能导致 CoreLocation 内部崩溃的细微错误,我不会感到惊讶。

我建议重构 HPBeaconManager 以便您可以在应用程序进入前台时根据需要重新初始化它,而无需创建新的对象实例。避免这种对象流失可能会使应用程序更加稳定。

关于ios - CoreLocation 线程崩溃 Crashed : com. apple.CoreLocation.ConnectionClient.0x16fcb870.events,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38237841/

10-11 17:24