在Swift 2.0中每隔n分钟更新一次背景中的位置

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Swift 2.0中每隔n分钟更新一次背景中的位置相关的知识,希望对你有一定的参考价值。

使用AppDelegate.swift中的以下代码,我可以每30秒获得一次位置更新。但是,在180秒后,backgroundTimeRemaining将执行后台执行。 plist在UIBackgroundModes中具有“location”标记 我有两个问题:

  1. 为什么backgroundTimeRemaining没有重置?
  2. 如果我执行startUpdatingLocation()然后stopUpdatingLocation()以节省电池,那么我将无法再次更新位置。

import UIKit
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {

    var window: UIWindow?
    let locationManager = CLLocationManager()
    var pos = 0
    var LatitudeGPS = NSString()
    var LongitudeGPS = NSString()
    var speedGPS = NSString()
    var Course = NSString()
    var Altitude = NSString()
    var bgtimer = NSTimer()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        // Override point for customization after application launch.
        return true
    }

    var backgroundUpdateTask: UIBackgroundTaskIdentifier!

    func beginBackgroundUpdateTask() {
        self.backgroundUpdateTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({
        self.endBackgroundUpdateTask()
        })
    }

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

    func doBackgroundTask() {

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
            self.beginBackgroundUpdateTask()

            // Do something
            self.StartupdateLocation()

            self.bgtimer = NSTimer.scheduledTimerWithTimeInterval(30, target: self, selector: "bgtimer:", userInfo: nil, repeats: true)
            NSRunLoop.currentRunLoop().addTimer(self.bgtimer, forMode: NSDefaultRunLoopMode)
            NSRunLoop.currentRunLoop().run()

            // End the background task.
            self.endBackgroundUpdateTask()
        })
    }

    func bgtimer(timer:NSTimer!){

        print("Fired from Background ************************************")

        updateLocation()

        print("Position Report: (pos)")
    }

    func applicationDidEnterBackground(application: UIApplication) {

        self.doBackgroundTask()
    }

    func StartupdateLocation() {
        locationManager.delegate = self
        locationManager.startUpdatingLocation()
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = kCLDistanceFilterNone
        locationManager.requestWhenInUseAuthorization()
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.pausesLocationUpdatesAutomatically = false
    }

    func updateLocation() {
        pos++

        //locationManager.startUpdatingLocation()
        //locationManager.stopUpdatingLocation()

        print("Latitude: (LatitudeGPS)")
        print("Longitude: (LongitudeGPS)")
        print("Speed: (speedGPS)")
        print("Heading: (Course)")
        print("Altitude BG: (Altitude)")
        print(UIApplication.sharedApplication().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)
    }
}

编辑***我在ViewController中初始化updateLocation后解决了问题。

答案
import UIKit
import CoreLocation
@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate,CLLocationManagerDelegate {
var window: UIWindow?
var locationManager = CLLocationManager()
var backgroundUpdateTask: UIBackgroundTaskIdentifier!
var bgtimer = Timer()
var latitude: Double = 0.0
var longitude: Double = 0.0
var current_time = NSDate().timeIntervalSince1970
var timer = Timer()
var f = 0
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    self.doBackgroundTask()
    return true
}


func applicationWillResignActive(_ application: UIApplication) {
}

func applicationWillEnterForeground(_ application: UIApplication) {
    print("Entering foreBackground")
}

func applicationDidBecomeActive(_ application: UIApplication) {
}

func applicationWillTerminate(_ application: UIApplication) {
}

func applicationDidEnterBackground(_ application: UIApplication) {
    print("Entering Background")
   // self.doBackgroundTask()
}

func doBackgroundTask() {

    DispatchQueue.main.async {

        self.beginBackgroundUpdateTask()

        self.StartupdateLocation()


        self.bgtimer = Timer.scheduledTimer(timeInterval:-1, target: self, selector: #selector(AppDelegate.bgtimer(_:)), userInfo: nil, repeats: true)
        RunLoop.current.add(self.bgtimer, forMode: RunLoopMode.defaultRunLoopMode)
        RunLoop.current.run()

        self.endBackgroundUpdateTask()

    }
}

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

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

func StartupdateLocation() {
    locationManager.delegate = self
    locationManager.desiredAccuracy = kCLLocationAccuracyBest
    locationManager.distanceFilter = kCLDistanceFilterNone
    locationManager.requestAlwaysAuthorization()
    locationManager.allowsBackgroundLocationUpdates = true
    locationManager.pausesLocationUpdatesAutomatically = false
    locationManager.startUpdatingLocation()
}

func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
    print("Error while requesting new coordinates")
}

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

    let locValue:CLLocationCoordinate2D = manager.location!.coordinate

    self.latitude = locValue.latitude
    self.longitude = locValue.longitude
    f+=1
    print("New Coordinates: (f) ")
    print(self.latitude)
    print(self.longitude)
}

@objc func bgtimer(_ timer:Timer!){
    sleep(2)
  /*  if UIApplication.shared.applicationState == .active {
         timer.invalidate()
    }*/
    self.updateLocation()
}

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

我添加了sleep函数来延迟调用该位置并将信息发送到服务器

由于这是在应用程序处于活动状态并且转到后台运行。如果只需要后台进程,请从didFinishLaunchingWithOptions中删除或注释函数self.doBackgroundTask(),并在applicationdidEnterBackground中删除self.doBackgroundTask()的注释。然后删除函数bgtimer()中的注释,因为一旦应用程序进入活动状态,后台进程就必须停止。

谢谢你只使用你的代码我能够为持续运行提供一些替代解决方案。

以上是关于在Swift 2.0中每隔n分钟更新一次背景中的位置的主要内容,如果未能解决你的问题,请参考以下文章

在 Swift 中每 x 分钟做一次

如何在 iOS 应用程序中每 n 分钟获取一次后台位置更新?

在响应式布局中每隔 n 行偏移一次

我想在 ios(swift) 中每五分钟加载一次 facebook 插页式广告

在后台永远运行Swift 2.0应用程序以更新服务器的位置

我想在swift中每隔10次显示一个警报