2014-10-09 103 views
15

我有后台模式对位置服务和瞄准位置(经度和纬度)发送到服务器每30分钟一班。现在我在控制台上打印相同的内容。它似乎工作了一段时间,但我想知道如何在这种情况下使用NSTimer。我应该从哪里调用它?发送位置,每30分钟更新斯威夫特

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 2014-10-09 04:44:17

回答

10

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

所以,可悲的是,后台任务机制并不适合您所期望的意图。但是,有一组特殊的背景模式,设计用于在一组狭窄的功能(VOIP,音频等)之外进行后台操作。欲了解更多信息,请参阅App Programming Guide for iOS: Background Execution实施长期运行任务部分。

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


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

+0

的答案嘿@Rob,谢谢。是的,我已经使用了背景模式进行定位,而且位置确实是应用程序的中心部分。此外,此应用程序仅适用于内部用户/临时用户。话虽如此,你能否给我一个例子或者说明我将如何在这里使用NSTimer? – psharma 2014-10-09 19:09:08

+0

嗨@Rob,谢谢你的回答。这有很大帮助。是的,我意识到这消耗电池,但因为它的特殊用途,它确定:)。另外,我会使用重大更改。现在我真的帮助我测试日志。再次感谢。 – psharma 2014-10-10 00:42:05

+0

@Rob,你所描述的方法在模拟器中为我工作,但不在设备上。任何可能出错的想法? – nbbk 2017-05-18 13:17:39

3

试试这个:

  • 让位置服务是独生子。通过NSNotificationCenter

NSNotification

  • AppDelegatewillEnterBackGround,你发送通知其注册的话,你的单身开始updatingLocation并将其发送到服务器时,接收到的位置数据。

  • 8

    的音符夫妇,因为我们一直在争取位置的问题,并与似乎并没有唤醒我们的后台应用程序挣扎。

    1. 只要您的应用程序没有被暂停,NSTimer就是好的。当然,它在后台,但只有它可以从iOS(APN,位置......)接收通知。最终,当你在BG中跑步时,你的计时器将停止射击。所以,你依靠其中一种BG模式来踢你。

    2. 如果您正在使用CLLocationManager.startUpdatingLocation,你会发现,你不干那些收到后位。特别是当电话放松并尝试入睡时。这是因为CLLocationManager.pausesLocationUpdatesAutomatically这个功能很差的功能,当它设置为“true”(DEFAULT设置)时,决定停止发送这些功能。您可以将其设置为“false”,并且您将继续获得您的位置更新。这几乎可以确保你的应用程序做你想要的。

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

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