Отправляйте обновления местоположения каждые 30 минут в Swift
У меня есть фоновый режим для служб определения местоположения, и я хочу отправлять данные о местоположении (широте и долготе) на сервер каждые 30 минут. Сейчас я печатаю то же самое в консоли. Кажется, это работает какое-то время, но мне интересно, как мне работать с NSTimer в этом случае. И откуда мне звонить?
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{}
плохая идея? Какие варианты мне выбрать?
3 ответа
Идея beginBackgroundTask...
заключается в запуске задачи конечной длины, чтобы, если пользователь покидает приложение, оно продолжало выполняться в фоновом режиме в течение некоторого короткого конечного периода времени (я полагаю, 3 минуты). И прежде чем истечет время, вы должны позвонить endBackgroundTask
или иначе приложение будет окончательно прервано.
Так что, к сожалению, механизм фоновых задач не совсем подходит для вашего желаемого намерения. Тем не менее, существует узкий набор специальных фоновых режимов, предназначенных для продолжения фоновой работы вне узкого набора функций (VOIP, аудио и т. Д.). Дополнительные сведения см. В разделе " Реализация долгосрочных задач " Руководства по программированию приложений для iOS: фоновое выполнение.
Теперь один из этих фоновых режимов предназначен для службы "определение местоположения". Итак, если это центральная функция вашего приложения, необходимая для правильной работы, то вы можете зарегистрироваться на location
фоновый режим, и ваше приложение будет продолжать работать в фоновом режиме. Оттуда вы можете следить за обновлениями местоположения и, если прошло достаточно времени, запустить какой-то процесс. Но если этот фоновый режим местоположения не является важной функцией вашего приложения, Apple, скорее всего, отклонит ваше приложение для запроса фонового режима, который ему не нужен.
Кстати, вы должны знать, что запуск стандартных служб определения местоположения может разрядить аккумулятор устройства. Вы можете подумать об использовании эффективной службы определения местоположения "значительное изменение" от аккумулятора. Это также дает возможность автоматически пробуждать ваше приложение каждый раз, когда пользователь перемещается на какое-то значительное расстояние (например, измеряется в км; я полагаю, что оно запускается при переходе на другую вышку сотовой связи).
Несколько замечаний, так как мы боролись с проблемами местоположения и с фоновыми приложениями, которые, кажется, не разбудили нас.
NSTimer хорош только до тех пор, пока ваше приложение не приостановлено. Конечно, это в фоновом режиме, но только потому, что он способен получать уведомления от iOS (APN, местоположение, ...). В конце концов, ваш таймер перестанет срабатывать, пока вы бежите в BG. Итак, вы полагаетесь на один из режимов BG, чтобы ударить вас.
Если вы используете CLLocationManager.startUpdatingLocation, вы заметите, что через некоторое время вы перестали получать их. Особенно когда телефон расслабляется и пытается уснуть. Это происходит из-за плохо документированной функции, называемой CLLocationManager.pausesLocationUpdatesAutomatics..., которая решает прекратить отправку тех, когда установлено значение "true" (настройка DEFAULT). Вы можете установить для него значение "false", и вы продолжите получать обновления своей позиции. Который в значительной степени убедится, что ваше приложение делает то, что вы хотите.
Как отмечалось выше, вы должны убедиться, что при получении обратного вызова locationManager.didUpdateLocations вы запускаете backgroundTask, чтобы ваше приложение работало во время обработки этой информации и отправки сетевых данных. Но вы, кажется, это понимаете.
Просто просыпаться достаточно долго, чтобы "записать" обновление местоположения, не так уж и плохо. Просто убедитесь, что вы не породили свой сетевой код, если вы не достигли 30-минутного ожидания.
Попробуй это:
- Сделайте синглтон для Службы определения местоположения. Зарегистрировано это с
NSNotification
- В
AppDelegate
"swillEnterBackGround
Вы отправляете уведомление черезNSNotificationCenter
тогда ваш синглтон начнет updatingLocation
и отправьте его на сервер, когда будут получены данные о местоположении.