在后台更新位置

ava*_*ava 3 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)

  }
}
Run Code Online (Sandbox Code Playgroud)

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

San*_*ari 10

几件事要改变.

步骤1:

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

在此输入图像描述

第2步:

当我针对stoped杀死应用程序位置更新时.

引用苹果文档

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

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

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

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

这意味着,您当前的位置管理器将没有多大用处,您应该创建一个新的实例并配置新实例并startMonitorSignificantLocationChanges再次调用.

因此iOS仅在您使用时才会向已终止的应用发送位置更新startMonitoringSignificantLocationChanges.

所有这些仅适用于您的应用程序已终止并且iOS在接收位置更新时重新启动它.但如果你的应用程序只是在后台,你不需要做任何使用的事情startMonitorSignificantLocationChanges

另一方面,startUpdatingLocation仅当app处于后台/前台模式时才会起作用.如果您的应用被暂停或终止,iOS将停止更新位置.

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

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

所以修改你的代码

 locationManager.startMonitoringSignificantLocationChange()
Run Code Online (Sandbox Code Playgroud)

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

错误1:

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

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

错误2:

  func updateLocation() {
    locationManager.startUpdatingLocation()
    locationManager.stopUpdatingLocation()
Run Code Online (Sandbox Code Playgroud)

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

错误3:

func StartupdateLocation() {
    locationManager.delegate = self
    locationManager.startUpdatingLocation()
Run Code Online (Sandbox Code Playgroud)

您的StartupdateLocation多次调用被调用,每次调用此方法时,您都会反复调用startUpdatingLocation位置管理器的同一实例.你不需要那样做!你可以打电话startUpdatingLocationstartMonitoringSignificantLocationChange只打一次.

  • 最后:“我在 applicationWillTerminate 中调用 self.doBackgroundTask() 但这不起作用”,这是因为如果您的应用程序使用后台执行,则不会调用 applicationWillTerminate。如果您在用户终止应用程序时提供后台执行(过期处理程序),则应用程序将不会被终止而是进入后台模式:) (2认同)
  • @SandeepBhandari ava 你们中有人有代码可以正确理解这个东西吗? (2认同)