微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

移动到后台时,使用 CoreLocation 会使我的应用程序崩溃

如何解决移动到后台时,使用 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,[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,lsr #7
    0x1a85f4108 <+40>:  and    x12,x12,lsr #48
    0x1a85f410c <+44>:  add    x13,x10,lsl #4
    0x1a85f4110 <+48>:  ldp    x17,x9,[x13],#-0x10
    0x1a85f4114 <+52>:  cmp    x9,x1
    0x1a85f4118 <+56>:  b.ne   0x1a85f4128               ; <+72>
    0x1a85f411c <+60>:  eor    x10,x1
    0x1a85f4120 <+64>:  eor    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,lsr #44
    0x1a85f4138 <+88>:  add    x12,lsl #4
    0x1a85f413c <+92>:  ldp    x17,#-0x10
    0x1a85f4140 <+96>:  cmp    x9,x1
    0x1a85f4144 <+100>: b.eq   0x1a85f411c               ; <+60>
    0x1a85f4148 <+104>: cmp    x9,#0x0                  ; =0x0 
    0x1a85f414c <+108>: ccmp   x13,ne
    0x1a85f4150 <+112>: b.hi   0x1a85f413c               ; <+92>
    0x1a85f4154 <+116>: b      0x1a85f44e0               ; _objc_msgSend_uncached
    0x1a85f4158 <+120>: and    x10,#0x7ffffffffffffe
    0x1a85f415c <+124>: autdb  x10,x16
    0x1a85f4160 <+128>: adrp   x9,235816
    0x1a85f4164 <+132>: add    x9,#0x4fa            ; =0x4fa 
    0x1a85f4168 <+136>: sub    x12,x9
    0x1a85f416c <+140>: lsr    x17,#55
    0x1a85f4170 <+144>: lsr    w9,w12,w17
    0x1a85f4174 <+148>: lsr    x17,#60
    0x1a85f4178 <+152>: mov    x11,#0x7fff
    0x1a85f417c <+156>: lsr    x11,x17
    0x1a85f4180 <+160>: and    x9,x11
    0x1a85f4184 <+164>: ldr    x17,[x10,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,#-0x8]
    0x1a85f419c <+188>: add    x16,x9
    0x1a85f41a0 <+192>: b      0x1a85f40f8               ; <+24>
    0x1a85f41a4 <+196>: b.eq   0x1a85f41c8               ; <+232>
    0x1a85f41a8 <+200>: and    x10,x0,#0x7
    0x1a85f41ac <+204>: asr    x11,#55
    0x1a85f41b0 <+208>: cmp    x10,#0x7                 ; =0x7 
    0x1a85f41b4 <+212>: csel   x12,eq
    0x1a85f41b8 <+216>: adrp   x10,319023
    0x1a85f41bc <+220>: add    x10,#0x820          ; =0x820 
    0x1a85f41c0 <+224>: ldr    x16,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 的最基本示例?谢谢。

解决方法

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。