在后台更新位置

时间:2017-11-15 06:04:25

标签: ios swift location-updates

我想获得用户位置,即使用户不使用app.now我可以在按下主页按钮后获得位置并且应用程序进入后台状态,但在几秒钟位置更新停止后。当我针对stoped杀死应用程序位置更新时。这是我在app delegate中的代码。

 let locationManager = CLLocationManager()
  var LatitudeGPS = String()
  var LongitudeGPS = String()
  var speedGPS = String()
  var Course = String()
  var Altitude = String()
  var bgtimer = Timer()

func applicationDidEnterBackground(_ application: UIApplication) {

    self.doBackgroundTask()
  }

  func beginBackgroundUpdateTask() {

    backgroundUpdateTask = UIApplication.shared.beginBackgroundTask(expirationHandler: {
      self.endBackgroundUpdateTask()
    })

  }

  func endBackgroundUpdateTask() {
    UIApplication.shared.endBackgroundTask(self.backgroundUpdateTask)
    self.backgroundUpdateTask = UIBackgroundTaskInvalid
  }
func doBackgroundTask() {

  DispatchQueue.global(qos: .background).async {

    self.beginBackgroundUpdateTask()
    self.StartupdateLocation()
    self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)
    RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
    RunLoop.current.run()
    self.endBackgroundUpdateTask()

  }


}


func bgtimer(timer:Timer!){
  print("Fired from Background ************************************")
  updateLocation()
}
  func StartupdateLocation() {
    locationManager.delegate = self
    locationManager.startUpdatingLocation()
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = kCLDistanceFilterNone
    locationManager.requestAlwaysAuthorization()
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.pausesLocationUpdatesAutomatically = false
  }

  func updateLocation() {
locationManager.startUpdatingLocation()
    locationManager.stopUpdatingLocation()
    print("Latitude: \(LatitudeGPS)")
    print("Longitude: \(LongitudeGPS)")
    print("Speed: \(speedGPS)")
    print("Heading: \(Course)")
    print("Altitude BG: \(Altitude)")
    DispatchQueue.main.async {
      print(UIApplication.shared.backgroundTimeRemaining)

    }
  }

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

    LatitudeGPS = String(format: "%.10f", manager.location!.coordinate.latitude)
    LongitudeGPS = String(format: "%.10f", manager.location!.coordinate.longitude)
    speedGPS = String(format: "%.3f", manager.location!.speed)
    Altitude = String(format: "%.3f", manager.location!.altitude)
    Course = String(format: "%.3f", manager.location!.course)

  }
}

我认为几秒钟后我的应用程序终止并且位置更新停止了。 我希望在20分钟后应用程序终止(操作系统或用户)停止更新位置以保持电池充电。 我的位置更新问题在哪里。

1 个答案:

答案 0 :(得分:8)

要改变一些事情。

第1步:

确保您已在项目的功能部分启用了位置更新后台模式,如下所示

enter image description here

第2步:

  

当我针对stoped。

杀死应用位置更新时

引用苹果文档

  

如果您启动此服务并且您的应用随后被终止,则   如果是新的,系统会自动将应用重新启动到后台   事件到了。在这种情况下,选项字典传递给了   application(:willFinishLaunchingWithOptions :)和   应用程序的应用程序(:didFinishLaunchingWithOptions :)方法   delegate包含指示您的应用程序所在的关键位置   由于位置事件而启动。重新启动后,您仍然必须   配置位置管理器对象并调用此方法继续   接收位置事件。当您重新启动位置服务时,   当前事件立即传递给您的代表。此外,   填充您的位置管理器对象的位置属性   在您开始定位之前,使用最新的位置对象   服务。

link:https://developer.apple.com/documentation/corelocation/cllocationmanager/1423531-startmonitoringsignificantlocati

在上述陈述中要注意的重要事项是

  

重新启动后,您仍然必须配置位置管理器对象   调用此方法继续接收位置事件。

意思是,您当前的位置管理器用处不大,您应该创建一个新的实例并配置新实例并再次调用startMonitorSignificantLocationChanges

因此,只有在您使用startMonitoringSignificantLocationChanges时,iOS才会向已终止的应用发送位置更新。

所有这些仅适用于您的应用已终止并且iOS在接收位置更新时重新启动它。但是,如果您的应用只是在后台,则无需使用startMonitorSignificantLocationChanges

另一方面,

startUpdatingLocation仅在app处于后台/前台模式时才有效。如果您的应用被暂停或被杀,iOS将停止更新位置。

  

如果您启动此服务并且您的应用已暂停,则系统会停止   交付事件,直到您的应用程序再次开始运行(在...中)   前景或背景)。如果您的应用程序被终止,则交付   新的位置事件完全停止。因此,如果您的应用需要   要在后台接收位置事件,它必须包括   其Info.plist中的UIBackgroundModes键(具有位置值)   文件。

link:https://developer.apple.com/documentation/corelocation/cllocationmanager/1423750-startupdatinglocation

所以修改你的代码

 locationManager.startMonitoringSignificantLocationChange()

好的是关于startMonitoringSignificantLocationChangesstartupdatinglocation的正确使用。现在计时代​​码中的错误。

错误1:

self.bgtimer = Timer.scheduledTimer(timeInterval: 30, target: self, selector: #selector(self.bgtimer(timer:)), userInfo: nil, repeats: true)

使用计时器及时获取位置更新。那不是它的工作方式!你不能永远运行Timer。一旦您的应用程序暂停或终止,计时器就会停止。位置管理器会在位置更改时通知应用,您应该只依赖它。您无法运行计时器以及时检查位置更新。它不会在暂停或终止状态下运行。

错误2:

  func updateLocation() {
    locationManager.startUpdatingLocation()
    locationManager.stopUpdatingLocation()

为什么在后续语句中启动和停止更新位置?这没有多大意义。

错误3:

func StartupdateLocation() {
    locationManager.delegate = self
    locationManager.startUpdatingLocation()

您的StartupdateLocation被多次调用,每次调用此方法时,您都会在同一个位置管理器实例上重复调用startUpdatingLocation。你不需要那样做!您只能拨打startUpdatingLocationstartMonitoringSignificantLocationChange一次。