locationManager didUpdateLocations 在挂起模式下崩溃

locationManager didUpdateLocations crashing in suspend mode

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

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

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

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() 继续。我仍在改变一切,但这似乎已经解决了问题。

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

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