2014-10-09 1 views
15

У меня есть фоновый режим для служб определения местоположения и направлен на отправку местоположения (широты и долготы) на сервер каждые 30 минут. На данный момент я печатаю то же самое в консоли. Кажется, это работает некоторое время, но мне интересно, как мне работать с NSTimer в этом случае. И откуда я должен его называть?Отправить обновление местоположения каждые 30 минут в Swift

import UIKit 
import CoreLocation 

@UIApplicationMain 
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate { 

    var window: UIWindow? 
    var locationManager = CLLocationManager() 

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

    func applicationWillResignActive(application: UIApplication) { 
     // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
     // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
    } 

    func applicationDidEnterBackground(application: UIApplication) { 
     // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
     // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 

     self.locationManager.delegate = self 
     self.locationManager.startUpdatingLocation() // I know i should be using signification location option here. this is just for testing now. 
    } 

    func locationManager(manager: CLLocationManager!, didUpdateToLocation newLocation: CLLocation!, fromLocation oldLocation: CLLocation!) { 
     self.sendBackgroundLocationToServer(newLocation); 
    } 

    func sendBackgroundLocationToServer(location: CLLocation) { 
     var bgTask = UIBackgroundTaskIdentifier() 
     bgTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler {() -> Void in 
      UIApplication.sharedApplication().endBackgroundTask(bgTask) 
     } 

     println(location.coordinate.latitude) 

     if (bgTask != UIBackgroundTaskInvalid) 
     { 
      UIApplication.sharedApplication().endBackgroundTask(bgTask); 
      bgTask = UIBackgroundTaskInvalid; 
     } 
    } 

    func applicationWillEnterForeground(application: UIApplication) { 
     // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 
     application.beginBackgroundTaskWithExpirationHandler{} 
    } 

    func applicationDidBecomeActive(application: UIApplication) { 
     // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
     application.beginBackgroundTaskWithExpirationHandler{} 
    } 

    func applicationWillTerminate(application: UIApplication) { 
     // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
     application.beginBackgroundTaskWithExpirationHandler{} 
    } 


} 

Возможно, звоните application.beginBackgroundTaskWithExpirationHandler{} - это плохая идея? Какие варианты я могу использовать здесь?

+0

Как и в сторону, метод делегата 'didUpdateToLocation: fromLocation' осуждается - обратитесь к CLLocationManagerDelegate документации – Paulw11

ответ

10

Идея beginBackgroundTask... заключается в том, чтобы запустить задачу с конечной длиной, так что если пользователь покинет приложение, он будет продолжать работать в фоновом задании на короткий, конечный период времени (на мой взгляд, 3 минуты). И до того, как закончится время, вы должны позвонить endBackgroundTask, иначе приложение будет прекращено.

Итак, к сожалению, механизм фоновой задачи не подходит для вашего желаемого намерения. Тем не менее, существует узкий набор специальных фоновых режимов, предназначенных для продолжения фоновой работы за пределами узкого набора функций (VOIP, аудио и т. Д.). Для получения дополнительной информации см. Раздел «Выполнение долговременных задач» раздел App Programming Guide for iOS: Background Execution.

Теперь один из этих режимов фона предназначен для службы «местоположения». Итак, если это центральная функция вашего приложения, важная для правильной функции, то вы можете зарегистрироваться в фоновом режиме location, и ваше приложение будет продолжать работать в фоновом режиме. Оттуда вы можете отслеживать обновления местоположения, и если прошло достаточное количество времени, активируйте некоторый процесс. Но если этот режим фонового местоположения не является существенной особенностью вашего приложения, Apple, скорее всего, отклонит ваше приложение для запроса фонового режима, который ему не нужен.


Кстати, вы должны знать, что запуск стандартных служб определения местоположения может привести к утечке аккумулятора устройства. Вы можете подумать об использовании аккумулятора "significant change" location service. Это также имеет преимущество автоматического пробуждения вашего приложения каждый раз, когда пользователь перемещает некоторое значительное расстояние (например, измеряется в км, я считаю, что это вызвано переходом на другую ячейку).

+0

Эй @Rob, спасибо за ответ. Да, я выбрал фоновый режим для местоположения, и действительно местоположение - это центр для приложения. Также это приложение предназначено только для внутреннего пользователя/ad-hoc. Сказав это, не могли бы вы привести мне пример или пролить свет на то, как я могу использовать NSTimer здесь? – psharma

+0

Эй, спасибо, спасибо за ответ. Это очень помогает. И да, я понимаю, что эта дренажная батарея, но поскольку ее для ad-hoc использования, это нормально :). Плюс да, я буду использовать значительные изменения. Сейчас я действительно помогаю тестировать журналы. Еще раз спасибо. – psharma

+0

@Rob, метод, который вы описали, работает для меня в симуляторе, но не на устройстве. Любая идея, что могло пойти не так? – nbbk

3

попробовать это:

  • Сделать синглтона для Location Service. Зарегистрировано это с NSNotification
  • В AppDelegate «s willEnterBackGround, вы отправить уведомление через NSNotificationCenter

тогда ваш одноточечно начнет updatingLocation и отправить его на сервер при получении данных местоположения.

8

Пара примечаний, так как мы боролись с проблемами местоположения и борются с фоновыми приложениями, которые, похоже, не разбудили нас.

  1. NSTimer подходит только при условии, что приложение не приостановлено. Конечно, это в фоновом режиме, но только потому, что он способен получать уведомления от iOS (APN, location, ...). В конце концов, ваш таймер прекратит стрельбу во время работы в BG. Таким образом, вы полагаетесь на один из режимов BG, чтобы пинать вас.

  2. Если вы используете CLLocationManager.startUpdatingLocation, вы заметите, что после этого вы перестали получать их.Особенно, когда телефон расслабляется и пытается спать. Это происходит из-за плохо документированной функции, называемой CLLocationManager.pausesLocationUpdatesAutomatically ... которая решает прекратить отправку тех, когда установлено значение «true» (параметр DEFAULT). Вы можете установить это значение «false», и вы продолжите получать обновления своей позиции. Который в значительной степени убедится, что ваше приложение делает то, что вы хотите.

  3. Как указано выше, вы должны убедиться, что когда вы получите обратный вызов locationManager.didUpdateLocations, вы начинаете backgroundTask, чтобы ваше приложение работало во время обработки этой информации и отправки сетевых данных. Но вы, кажется, это понимаете.

  4. Просто проснуться достаточно долго, чтобы «записать» обновление местоположения не так уж плохо. Просто убедитесь, что вы не порождаете свой сетевой код, если вы явно не нажмете на свое 30-минутное ожидание.

Смежные вопросы