永远在后台运行 Swift 2.0 应用程序以将位置更新到服务器 [英] Run a Swift 2.0 app forever in background to update location to server

查看:21
本文介绍了永远在后台运行 Swift 2.0 应用程序以将位置更新到服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have written the below code that has a timer that calls a callback function every minute. When the app goes to the background I have started another timer that calls the same callback method, but the background timer works for only three minutes.

我了解 Apple 只允许后台任务执行三分钟.我的应用更像是一个跟踪应用,即使应用在后台,也会每分钟跟踪用户的位置,所以我需要实现这个功能.

I understand that Apple allows background tasks for only three minutes. My app is more like a tracking app that tracks the location of the user every minute even when the app is in background, so I need to implement this functionality.

得知要使用beginBackgroundTaskWithExpirationHandler,但不知道我的实现是否正确.

I learned that beginBackgroundTaskWithExpirationHandler is to be used but I don't know whether my implementation is correct.

注意:我在 plist toApp 寄存器中有必需的后台模式以进行位置更新.

Note: I have Required background modes in plist toApp registers for location updates.

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

Any working code or links are much appreciated.

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 中定期位置更新有点棘手.有一个很好的线程讨论了这个问题,你可以阅读更多 这里

Periodic location updates are a bit tricky in IOS.There's a good thread that discusses this, you can read more here

无论您的计时器是否正在运行,iOS 都会在几分钟后终止您的应用.不过有一种方法可以解决这个问题,我在编写离子应用程序时必须做类似的事情,这样你就可以查看这个 这里,该链接有一个 swift 类,用于管理 iO 中的定期位置更新.

iOS will terminate your app after a few minutes, regardless if your timer is running or not. There is a way around this though, I had to do something similar when writing an ionic app so you can check out the code for this here, that link has a swift class that manages the periodic location updates in iOs.

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

In order to get periodic locations in the background, and not drain the battery of the device, you need to play with the accuracy of the location records, lower the accuracy of the location manager setting its desiredAccuracy to kCLLocationAccuracyThreeKilometers, then, every 60 seconds you need to change the accuracy to kCLLocationAccuracyBest, this will enable the delegate to get a new, accurate location update, then revert the accuracy back to low. The timer needs to be initialized every time an update is received.

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

There's also a way to wake up the app in the background after its been killed by the user, use the app delegate to have the app listen for significant changes in location before its killed. This will wake up the app in the background when the user's location makes a big jump (can be around 200ms). When the app wakes up, stop monitoring for significant changes and restart the location services as usual to continue the periodic updates.

希望这会有所帮助.

更新

在 Swift 2 中,您还需要:

In Swift 2 you'll also need:

self.locationManager.allowsBackgroundLocationUpdates = true

这篇关于永远在后台运行 Swift 2.0 应用程序以将位置更新到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆