在Swift中每30分钟发送一次位置更新

时间:2014-10-09 02:32:28

标签: ios ios7 swift ios8 core-location

我有位置服务的后台模式,目标是每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 个答案:

答案 0 :(得分:10)

beginBackgroundTask...的想法是开始一个有限长度的任务,这样如果用户离开应用程序,它将继续在后台任务中运行一段短暂的有限时间(3分钟,我相信) 。在时间用完之前,您必须致电endBackgroundTask,否则该应用将被立即终止。

所以,遗憾的是,后台任务机制并不适合你想要的意图。但是,有一组狭窄的特殊背景模式,用于在一组狭窄的功能(VOIP,音频等)之外继续进行背景操作。有关详细信息,请参阅App Programming Guide for iOS: Background Execution实施长期运行任务部分。

现在,其中一种背景模式适用于"位置"服务。因此,如果这是您的应用的核心功能,对于正常功能至关重要,那么您可以注册location后台模式,您的应用将继续在后台运行。从那里,您可以监视位置更新,如果已经过了足够的时间,则触发一些进程。但是,如果此背景位置模式不是您应用的基本功能,Apple可能会拒绝您的应用请求其不需要的后台模式。


顺便说一句,您应该知道启动标准位置服务可能会耗尽设备电池。您可以考虑使用电池效率"significant change" location service。这也具有每次用户移动一些显着距离时自动唤醒您的应用程序的优点(例如以km为单位测量;我相信它是通过移动到不同的手机信号塔触发的。)

答案 1 :(得分:8)

一些注意事项,因为我们一直在与位置问题作斗争,并且正在努力应对那些似乎没有唤醒我们的后台应用程序。

  1. 只要您的申请未被暂停,NSTimer就会很好。当然,它在后台,但只有它能够接收来自iOS(APN,位置,...)的通知。最终,当你在BG中跑步时,你的计时器将停止射击。所以,你依靠其中一种BG模式来踢你。

  2. 如果你正在使用CLLocationManager.startUpdatingLocation,你会注意到你稍后退出了那些。特别是当手机放松并试图入睡时。这是因为文档记录不佳,称为CLLocationManager.pausesLocationUpdatesAutomatically ...当设置为“true”(DEFAULT设置)时,它决定停止发送它们。您可以将其设置为“false”,然后您将继续获得您的职位更新。这将确保您的应用程序能够满足您的需求。

  3. 如上所述,您必须确保在获得locationManager.didUpdateLocations回调时,开始使用backgroundTask以在处理该信息并发送网络数据时保持应用程序正常运行。但你似乎明白这一点。

  4. 只需醒来足够长时间来“记录”位置更新并不是那么糟糕。只要确保你没有产生你的网络代码,除非你明显达到30分钟的预期。

答案 2 :(得分:3)

试试这个:

  • 为位置服务制作单身人士。使用NSNotification
  • 注册
  • AppDelegate的{​​{1}}中,您通过willEnterBackGround发送通知

然后,您的单身人士将启动NSNotificationCenter并在收到位置数据时将其发送到服务器。