2016-03-22 1 views
11

Я написал ниже код с таймером, который вызывает функцию обратного вызова каждую минуту. Когда приложение переходит на задний план, я запустил еще один таймер, который вызывает тот же метод обратного вызова, но фоновый таймер работает всего три минуты.Запустите приложение Swift 2.0 навсегда, чтобы обновить местоположение на сервере

Я понимаю, что Apple позволяет выполнять фоновые задачи всего три минуты. Мое приложение больше похоже на приложение отслеживания, которое отслеживает местоположение пользователя каждую минуту, даже когда приложение находится в фоновом режиме, поэтому мне нужно реализовать эту функцию.

Я узнал, что должен использоваться beginBackgroundTaskWithExpirationHandler, но я не знаю, верна ли моя реализация.

Примечание: у меня есть требуемые фоновые режимы в регистре plist toApp для обновления местоположения.

Любой рабочий код или ссылки очень ценятся.

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) 
     }) 
    } 
} 

ответ

16

Периодические обновления местоположения немного сложнее в хорошем потоке IOS.There, что говорит об этом, вы можете прочитать больше here

IOS прекратит свое приложение через несколько минут, независимо от того, таймер работает или нет. Существует способ обойти это, хотя я должен был сделать что-то подобное при написании ионного приложения, чтобы вы могли проверить код для этого here, эта ссылка имеет быстрый класс, который управляет периодическими обновлениями местоположения в iOS.

Для того чтобы получить периодические местоположения в фоновом режиме и не разряжать аккумулятор устройства, вам необходимо играть с точностью записей местоположения, снизить точность управления местоположением, задав его требуемую точность для kCLLocationAccuracyThreeKilometers, каждые 60 секунд вам нужно изменить точность до kCLLocationAccuracyBest, это позволит делегату получить новое точное обновление местоположения, а затем вернет точность обратно к минимуму. Таймер необходимо инициализировать каждый раз при получении обновления.

Существует также способ пробудить приложение в фоновом режиме после его уничтожения пользователем, использовать делегат приложения, чтобы приложение прослушивало значительные изменения в местоположении до его уничтожения. Это запустит приложение в фоновом режиме, когда местоположение пользователя совершит большой прыжок (может быть около 200 мс). Когда приложение просыпается, прекратите мониторинг значительных изменений и перезапустите службы определения местоположения, как обычно, для продолжения периодических обновлений.

Надеюсь, это поможет.

Update

В Swift 2 вам также понадобится:

self.locationManager.allowsBackgroundLocationUpdates = true 
+0

Спасибо за помощь ... Я совершенно новый для Swift ... Я пытался изменить значение точности каждые 60 секунд, как вы сказали ... Я все равно получаю тот же результат (т. Е. Приложение запускает и обновляет местоположение только для через три минуты после того, как он был вставлен в фокус) – Carey

+1

Здравствуйте, извините, я забыл упомянуть, и я считаю, что этого не хватает в вашем коде, вам также необходимо включить фоновые местоположения в вашем менеджере местоположений, что-то вроде строк self.locationManager.allowBackgroundLocationUpdates = true –

+0

Большое спасибо bro.It сработал! – Carey

0

Вы можете использовать библиотеку для background location tracking, пример использования:

var backgroundLocationManager = BackgroundLocationManager() 

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { 

    backgroundLocationManager.startBackground() { result in 
      if case let .Success(location) = result { 
       LocationLogger().writeLocationToFile(location: location) 
      } 
    } 

    return true 
} 

Это работает, когда приложение убиты или приостановлены.