首页 > 解决方案 > locationManager didUpdateLocations 在挂起模式下崩溃

问题描述

当我的屏幕被锁定超过 10 秒左右并且我的位置发生变化时,会触发 didUpdateLocations 但代码在中途停止执行。具体来说,它停在以下行:print("locationManager: triggering toggleStatus")。它执行 print 语句,但不会更进一步。我尝试用其他代码替换对 eco?.toggleStatus() 函数的调用,它仍然在 print 语句之后停止。不管打印语句下面的代码是什么。locationManager.allowsBackgroundLocationUpdates 设置为 true。

我正在使用真正的 iPhone 来测试这段代码。我注意到,当模拟器处于锁定模式时,代码会在模拟器上全程运行(包括调用和执行 toggleStatus())。我猜这是因为模拟器只是将应用程序置于后台模式而不是暂停它,但我不确定。

另一件需要注意的事情:几周前我在我的 iPhone 上测试了这段代码,它似乎工作正常,包括在手机被锁定时。几周后,我注意到它在打印语句处停止。

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    let location = locations[locations.count - 1]

    if location.horizontalAccuracy > 0 {

        var latitude = round(location.coordinate.latitude*1000000)/1000000
        let longitude = round(location.coordinate.longitude*1000000)/1000000
        print("locationManager: latitude is: \(latitude)")
        print("locationManager: longitude is: \(longitude)")


        if settingNewHomeLocation == true {
            keychain.set(String(format:"%f", latitude), forKey: "bLatitude", withAccess: .accessibleAlways)
            keychain.set(String(format:"%f", longitude), forKey: "bLongitude", withAccess: .accessibleAlways)
            print("base latitude is: \(keychain.get("bLatitude")!)")
            print("base longitude is: \(keychain.get("bLongitude")!)")
            settingNewHomeLocation = false
        }

        if keychain.get("bLatitude") != nil { 

            let bLatitude = Double(keychain.get("bLatitude")!)
            let bLongitude = Double(keychain.get("bLongitude")!)

            let baseLocation = CLLocation(latitude: bLatitude!, longitude: bLongitude!)
            let distance = CLLocation(latitude: latitude, longitude: longitude).distance(from: baseLocation)
            print("locationManager: distance is: \(distance)")

            if distance > 100 {

                print("locationManager: triggering toggleStatus")
                eco?.toggleStatus()
            }

        } else {
            print("No home location set")
        }
    }
}

解决方案:下面的 Anand 解决方案(删除钥匙串引用)似乎是正确的。我检查了 toggleStatus() 开头的打印语句,它包含对导致崩溃的钥匙串项的引用。此钥匙串引用与 didUpdate 函数中的引用之间的区别在于它存储在使用 SwiftKeychainWrapper 创建的钥匙串中。我之前在开发应用程序时遇到了 SwiftKeychainWrapper 的其他一些问题,并在编写其余代码时切换到 KeychainSwift。出于纯粹懒惰的原因(这个应用程序只适合我),我从来没有回去切换过 toggleStatus() 中的值。删除引用允许 toggleStatus() 继续。我仍在改变一切,但这似乎已经解决了问题。

标签: swiftcllocationmanagerlocationmanager

解决方案


您似乎将位置详细信息存储在钥匙串中。当应用程序处于挂起状态时访问钥匙串并不总是没有错误。它的行为对于背景案例来说是完全奇怪的。在设备中启用 Touch ID / Face ID 后,设备锁定时的情况会更加复杂。

假设您的设备启用了 Touch ID / Face ID 并且设备已锁定。现在,当应用程序接收到位置更新时,它会尝试访问钥匙串,但设备被锁定并启用了 Touch ID / Face ID。这种组合有时有效,有时无效。不过,我正在寻找为什么会发生这种情况。


推荐阅读