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

标签 ios iphone swift background core-location

我写了下面的代码,它有一个每分钟调用一次回调函数的定时器。当应用程序进入后台时,我启动了另一个调用相同回调方法的计时器,但后台计时器仅工作三分钟。

我知道 Apple 只允许后台任务持续三分钟。我的应用更像是一个跟踪应用,即使在应用处于后台时也会每分钟跟踪用户的位置,因此我需要实现此功能。

我了解到要使用beginBackgroundTaskWithExpirationHandler,但我不知道我的实现是否正确。

注意:我在 plist toApp registers for location updates 中有 Required background modes。

非常感谢任何有效的代码或链接。

override func viewDidLoad() {
    super.viewDidLoad()

    timeInMinutes = 1 * 60

    self.locationManager.requestAlwaysAuthorization()

    self.locationManager.requestWhenInUseAuthorization()

    if CLLocationManager.locationServicesEnabled() {
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        locationManager.startUpdatingLocation()
    }

    var timer = NSTimer.scheduledTimerWithTimeInterval( timeInMinutes, target: self, selector: "updateLocation", userInfo: nil, repeats: true)
}

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate

    self.latitude = locValue.latitude
    self.longitude = locValue.longitude

    if UIApplication.sharedApplication().applicationState == .Active {

    } else {
        backgroundTaskIdentifier = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({ () -> Void in
            self.backgroundTimer.invalidate()
            self.backgroundTimer = NSTimer.scheduledTimerWithTimeInterval( 60.0, target: self, selector: "updateLocation", userInfo: nil, repeats: true)
        })
    }
}

func updateLocation() {
    txtlocationLabel.text = String(n)
    self.n = self.n+1

    var timeRemaining = UIApplication.sharedApplication().backgroundTimeRemaining

    print(timeRemaining)

    if timeRemaining > 60.0 {
        self.GeoLogLocation(self.latitude,Longitude: self.longitude) {
            results in
            print("View Controller: \(results)")
            self.CheckResult(String(results))
        }
    } else {
        if timeRemaining == 0 {
            UIApplication.sharedApplication().endBackgroundTask(backgroundTaskIdentifier)
        }

        backgroundTaskIdentifier2 = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({ () -> Void in
            self.backgroundTimer.invalidate()
            self.backgroundTimer = NSTimer.scheduledTimerWithTimeInterval( 60.0, target: self, selector: "updateLocation", userInfo: nil, repeats: true)
        })
    }
}

最佳答案

周期性位置更新在 IOS 中有点棘手。有一个很好的线程讨论这个,你可以阅读更多 here

iOS 将在几分钟后终止您的应用程序,无论您的计时器是否正在运行。不过有办法解决这个问题,我在编写 ionic 应用程序时必须做类似的事情,所以你可以查看这个 here 的代码。 ,该链接有一个 swift 类,用于管理 iO 中的定期位置更新。

为了在后台获取周期性位置,并且不耗尽设备的电池,您需要使用位置记录的准确性,降低位置管理器的准确性,将其 desiredAccuracy 设置为 kCLLocationAccuracyThreeKilometers,然后,每60 秒后,您需要将精度更改为 kCLLocationAccuracyBest,这将使代理能够获得新的准确位置更新,然后将精度恢复为低精度。每次收到更新时都需要初始化定时器。

还有一种方法可以在应用程序被用户杀死后在后台唤醒应用程序,使用应用程序委托(delegate)让应用程序在被杀死之前监听位置的重大变化。这将在用户的位置大幅跳跃(大约 200 毫秒)时在后台唤醒应用程序。当应用程序唤醒时,停止监视重大变化并像往常一样重启位置服务以继续定期更新。

希望这对您有所帮助。

更新

在 Swift 2 中你还需要:

self.locationManager.allowsBackgroundLocationUpdates = true

关于ios - 永远在后台运行 Swift 2.0 应用程序以将位置更新到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36148589/

相关文章:

ios - 针对 iOS 商店存档错误验证应用程序

ios - 在 Game Center 中启用 Facebook Like 按钮

ios - 即使在导入 MapKit 后仍使用未声明的类型 'MKMapView'

ios - 有没有办法检查字符串是否包含 Unicode 字母?

ios - 调用 performSeguewithIdentifier 不会调用 shouldperformseguewithIdentifier

iphone - 如何在 iOS 中将 unsigned char 转换为 NSString

iPhone:根据 Storyboard正确隐藏 UITableViewCell 中的附件按钮

ios - 如何从 cellForItemAtIndexPath 设置 UICollectionViewCell 高度?

iPhone - 使用核心数据中的子对象从父表获取数据

ios - UIScrollView 取消/停止 setContentOffset :<CGPoint>animate:YES animation