iOS 11,当用户强制关闭应用程序时,应用程序不更新位置

6
我正在开发一款需要实时定位的应用程序,因此我使用了startMonitoringSignificantLocationChanges,在 iOS 10 模拟器上一切正常,即使用户从应用程序切换器中强制退出应用程序也是如此。同时,在调试模式下使用高速公路行驶选项,以保持位置变化。
但对于 iOS 11 模拟器: 当应用程序处于后台或前台模式时,服务器会更新用户的实时位置,但当应用程序被强制退出时,这种情况就不再存在。
服务器没有收到更新的位置信息,我甚至在didFinishLaunching中设置了一个断点,并使用了“等待可执行文件启动”的设置来检查是否有回调,但在 iOS 11 中没有,而在 iOS 10 中有。
我还更新了 info.plist 中适用于 iOS 11 的相应值,并确认我已授予“始终”权限。 我正在使用位置管理器对象的单例模式,代码如下:
func setupLocationManager(){

    locationManager = CLLocationManager()
    locationManager.delegate = self
    locationManager.pausesLocationUpdatesAutomatically = false
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.requestAlwaysAuthorization()
    locationManager.distanceFilter = 100.0
    locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
    locationManager.startMonitoringSignificantLocationChanges()
    locationManager.startUpdatingLocation()
}

在应用程序委托中:

if let _ = launchOptions?[UIApplicationLaunchOptionsKey.location] {

        ChatSocketHelper.sharedInstance.socket.on("connect") { data, ack in

            if let coordinate = LocationManager.shared.currentLocation?.coordinate{

                ChatSocketHelper.sharedInstance.updateLocation([coordinate.longitude, coordinate.latitude])
            }
        }   
    }

在位置委托中:

extension LocationManager : CLLocationManagerDelegate{

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

        guard let locationObject = locations.last else {return}

        //update to closest accuracy
        currentLocation = locationObject

        if ChatSocketHelper.sharedInstance.socket != nil{
ChatSocketHelper.sharedInstance.updateLocation([locationObject.coordinate.longitude, locationObject.coordinate.latitude])
        }
    }
}

这是iOS 11已知的问题吗?当用户强制关闭程序后,位置功能会失效吗?我搜索了一些相关的资料,发现类似的蓝牙问题,但没有针对位置变化的重要信息。
例如:这个链接。 编辑:此外,这篇文章提到更新速度“缓慢”,但我根本就没有收到更新。

1
当应用程序被强制退出时,它不再在后台运行。 应用程序进程完全终止。 你为什么期望能够获取位置呢? - Eugene Dudnyk
2
因为startMonitoringSignificantLocationChangesgeoFencing是为此目的而设计的。当应用程序被用户终止时,您应该在didFinishLaunching中获得一个带有“Locations”键的回调。 - Rikh
您的目标Info.plist文件的UIBackgroundModes数组中是否有“location”? - Eugene Dudnyk
是的,实际上我会同时启用所需能力中的复选框。 - Rikh
@Rikh,我尝试了同样的事情,但是当我杀死应用程序后,它仍然在状态栏中显示位置图标,这意味着它仍然存在以捕获位置的重大变化。你能在关闭应用程序后看到状态栏中的位置图标吗? - Hardik Shah
它偶尔显示图标并随机停止更新位置。我使用模拟器中的高速公路驾驶模式进行了检查。当运行相同的代码时,有时我可以看到空心位置图标而不是填充的图标。当我重新启动应用程序时,它立即跳转到正确的位置,这可能是几英里之外,因此我知道位置正在改变,但回调在iOS 11上没有发生。 - Rikh
1个回答

1
我花了很长时间来调试并寻找可靠的答案。基本上,背景和前景位置更新都按预期工作。现在让我们来谈谈真正的问题,即应用程序的停止模式(主要是用户强制退出)。
据我所知,当我通过模拟器测试时,位置更新无法正常工作的原因可能是因为我测试的距离远远不够,或者可能是因为“significantLocationChanges”依赖于网络的变化(切换到不同的塔或其他什么)。但是,当我使用真实设备进行杀死场景测试并行驶相当长的距离时,我发现结果是各种各样的,但基本上位置确实有更新,尽管更新并不一致。现在这种一致性也可能是旅行时网络连接不良造成的,但我无法确定。
在汽车上行驶15-20分钟(超过3.8公里的距离),当应用程序被杀死时,在一天内将位置发送到服务器4-5次,而在不同路线行驶相同时间时,则为2-3次。同样,这可能是由于网络条件差或网络切换的频率导致的。
如果您期望背景和前景级别的准确性/频率,则是不可能的。目前根本不可能。
现在,我尝试使用动态地理围栏来监控位置更新,但这有点失败了。每当我从操作系统得到用户退出/进入地理围栏设置的回调时,我就设置一个新的地理围栏。现在这些回调发生了一段时间,但有时它们会突然停止,整个地理围栏区域被完全跳过,或者如果车辆移动得太快,地理围栏就不会提供回调,因为我们需要满足条件才能获得这些回调。更多信息可以在这里阅读。

从上面链接的文档中可以看到,“测试iOS应用程序的区域监视支持”

在iOS模拟器或设备上测试区域监控代码时,请注意,区域事件可能不会在越过区域边界后立即发生。为了防止虚假通知,iOS只有在满足特定的门槛条件后才会提供区域通知。具体而言,用户的位置必须越过区域边界,移动到距离边界一定距离,并保持该最小距离至少20秒钟,然后才会报告通知。具体的门槛距离由硬件和当前可用的位置技术确定。例如,如果禁用Wi-Fi,则区域监视的准确性会显著降低。但是,出于测试目的,您可以假设最小距离约为200米。
基本上,您可以使用startMonitoringSignificantLocationChanges获取位置更新,但精度和频率并不是您可以依赖或估计的东西。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接