首页 > 解决方案 > 移动到后台时,使用 CoreLocation 会使我的应用程序崩溃

问题描述

我在这里有一个非常简单的 iOS 应用程序(Swift 5 和 XCode 12.3)。它只有两个按钮来启动和停止 CLLocationManager。当应用程序处于前台时,一切似乎都运行良好。问题是即使应用程序不在前台,我也想继续接收更新。我激活了复选标记“后台模式”,“位置更新”。但它不起作用。一旦我将应用程序置于后台(从我的 iPhone XR 底部向上滑动),它就会崩溃并出现以下错误:

libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument
terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument

我还在 Info.plist 中提供了“隐私 - 始终位置和使用时的使用说明”和“隐私 - 使用时的位置使用说明”的键。我的视图控制器的代码如下:

import UIKit
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {
    var locationManager: CLLocationManager!

    override func viewDidLoad() {
        super.viewDidLoad()
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.showsBackgroundLocationIndicator = true
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.pausesLocationUpdatesAutomatically = false
        locationManager.activityType = .other
        locationManager.desiredAccuracy = kCLLocationAccuracyBestForNavigation
        locationManager.distanceFilter = kCLDistanceFilterNone
    }

    @IBAction func play(_ sender: UIButton) {
        locationManager.requestAlwaysAuthorization()
        self.locationManager.startUpdatingLocation()
    }

    @IBAction func stop(_ sender: UIButton) {
        locationManager.stopUpdatingLocation()
    }

    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        locations.forEach { (location) in
            print(location)
        }
        print("\n")
    }
}

堆栈跟踪看起来像并报告了一个 SIGABRT:

libsystem_kernel.dylib`__pthread_kill:
    0x1c153240c <+0>:  mov    x16, #0x148
    0x1c1532410 <+4>:  svc    #0x80
->  0x1c1532414 <+8>:  b.lo   0x1c1532434               ; <+40>
    0x1c1532418 <+12>: pacibsp 
    0x1c153241c <+16>: stp    x29, x30, [sp, #-0x10]!
    0x1c1532420 <+20>: mov    x29, sp
    0x1c1532424 <+24>: bl     0x1c150ec20               ; cerror_nocancel
    0x1c1532428 <+28>: mov    sp, x29
    0x1c153242c <+32>: ldp    x29, x30, [sp], #0x10
    0x1c1532430 <+36>: retab  
    0x1c1532434 <+40>: ret    

有时它也会因 EXC_BAD_ACCESS 和以下冗长的堆栈跟踪而崩溃:

libobjc.A.dylib`objc_msgSend:
    0x1a85f40e0 <+0>:   cmp    x0, #0x0                  ; =0x0 
    0x1a85f40e4 <+4>:   b.le   0x1a85f41a4               ; <+196>
    0x1a85f40e8 <+8>:   ldr    x13, [x0]
    0x1a85f40ec <+12>:  and    x16, x13, #0x7ffffffffffff8
    0x1a85f40f0 <+16>:  xpacd  x16
    0x1a85f40f4 <+20>:  mov    x15, x16
->  0x1a85f40f8 <+24>:  ldr    x11, [x16, #0x10]
    0x1a85f40fc <+28>:  tbnz   w11, #0x0, 0x1a85f4158    ; <+120>
    0x1a85f4100 <+32>:  and    x10, x11, #0xffffffffffff
    0x1a85f4104 <+36>:  eor    x12, x1, x1, lsr #7
    0x1a85f4108 <+40>:  and    x12, x12, x11, lsr #48
    0x1a85f410c <+44>:  add    x13, x10, x12, lsl #4
    0x1a85f4110 <+48>:  ldp    x17, x9, [x13], #-0x10
    0x1a85f4114 <+52>:  cmp    x9, x1
    0x1a85f4118 <+56>:  b.ne   0x1a85f4128               ; <+72>
    0x1a85f411c <+60>:  eor    x10, x10, x1
    0x1a85f4120 <+64>:  eor    x10, x10, x16
    0x1a85f4124 <+68>:  brab   x17, x10
    0x1a85f4128 <+72>:  cbz    x9, 0x1a85f44e0           ; _objc_msgSend_uncached
    0x1a85f412c <+76>:  cmp    x13, x10
    0x1a85f4130 <+80>:  b.hs   0x1a85f4110               ; <+48>
    0x1a85f4134 <+84>:  add    x13, x10, x11, lsr #44
    0x1a85f4138 <+88>:  add    x12, x10, x12, lsl #4
    0x1a85f413c <+92>:  ldp    x17, x9, [x13], #-0x10
    0x1a85f4140 <+96>:  cmp    x9, x1
    0x1a85f4144 <+100>: b.eq   0x1a85f411c               ; <+60>
    0x1a85f4148 <+104>: cmp    x9, #0x0                  ; =0x0 
    0x1a85f414c <+108>: ccmp   x13, x12, #0x0, ne
    0x1a85f4150 <+112>: b.hi   0x1a85f413c               ; <+92>
    0x1a85f4154 <+116>: b      0x1a85f44e0               ; _objc_msgSend_uncached
    0x1a85f4158 <+120>: and    x10, x11, #0x7ffffffffffffe
    0x1a85f415c <+124>: autdb  x10, x16
    0x1a85f4160 <+128>: adrp   x9, 235816
    0x1a85f4164 <+132>: add    x9, x9, #0x4fa            ; =0x4fa 
    0x1a85f4168 <+136>: sub    x12, x1, x9
    0x1a85f416c <+140>: lsr    x17, x11, #55
    0x1a85f4170 <+144>: lsr    w9, w12, w17
    0x1a85f4174 <+148>: lsr    x17, x11, #60
    0x1a85f4178 <+152>: mov    x11, #0x7fff
    0x1a85f417c <+156>: lsr    x11, x11, x17
    0x1a85f4180 <+160>: and    x9, x9, x11
    0x1a85f4184 <+164>: ldr    x17, [x10, x9, lsl #3]
    0x1a85f4188 <+168>: cmp    x12, w17, uxtw
    0x1a85f418c <+172>: b.ne   0x1a85f4198               ; <+184>
    0x1a85f4190 <+176>: sub    x17, x16, x17, lsr #32
    0x1a85f4194 <+180>: br     x17
    0x1a85f4198 <+184>: ldursw x9, [x10, #-0x8]
    0x1a85f419c <+188>: add    x16, x16, x9
    0x1a85f41a0 <+192>: b      0x1a85f40f8               ; <+24>
    0x1a85f41a4 <+196>: b.eq   0x1a85f41c8               ; <+232>
    0x1a85f41a8 <+200>: and    x10, x0, #0x7
    0x1a85f41ac <+204>: asr    x11, x0, #55
    0x1a85f41b0 <+208>: cmp    x10, #0x7                 ; =0x7 
    0x1a85f41b4 <+212>: csel   x12, x11, x10, eq
    0x1a85f41b8 <+216>: adrp   x10, 319023
    0x1a85f41bc <+220>: add    x10, x10, #0x820          ; =0x820 
    0x1a85f41c0 <+224>: ldr    x16, [x10, x12, lsl #3]
    0x1a85f41c4 <+228>: b      0x1a85f40f4               ; <+20>
    0x1a85f41c8 <+232>: mov    x1, #0x0
    0x1a85f41cc <+236>: movi   d0, #0000000000000000
    0x1a85f41d0 <+240>: movi   d1, #0000000000000000
    0x1a85f41d4 <+244>: movi   d2, #0000000000000000
    0x1a85f41d8 <+248>: movi   d3, #0000000000000000
    0x1a85f41dc <+252>: ret  

我不知道这些痕迹是什么意思,也没有在网上找到确凿的解释。有人可以为我提供一些见解(或者实际上只是在后台运行 CLLocationManager 的最基本示例?谢谢。

标签: iosswiftcore-locationcllocationmanager

解决方案


好的。经过一些额外的实验,我发现了这个问题。一切实际上都像宣传的那样工作。print但是,在物理设备上测试后台模式时,您永远不应该在函数中使用调用。只要使用模拟器,我上面发布的示例就可以工作。但是这些print语句在真实设备上确实会崩溃。我想,原因是真实设备没有连接终端。


推荐阅读