2014-10-09 2 views
15

위치 서비스를 위해 백그라운드 모드를 설정하고 30 분마다 위치를 위도와 경도로 보내려고합니다. 지금은 콘솔에 같은 것을 인쇄하고 있습니다. 그것은 잠시 동안 작동하는 것하지만 나는이 경우 NSTimer와 어떻게 작동하는지 궁금합니다. 그리고 어디에서 불러야합니까?Swift에서 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

: fromLocation'가되지 않습니다 - 대답에 대한 CLLocationManagerDelegate 워드 프로세서 – Paulw11

답변

10

아이디어는 beginBackgroundTask...입니다. 사용자가 앱을 나가면 일정한 짧은 시간 (3 분) 동안 백그라운드 작업을 계속 실행할 수 있도록 유한 길이의 작업을 시작하는 것이 좋습니다. 그리고 시간이 다 떨어지기 전에 endBackgroundTask에 전화해야합니다. 그렇지 않으면 앱이 일시적으로 종료됩니다.

슬프게도 백그라운드 작업 메커니즘이 원하는 의도에 적합하지 않습니다. 그러나 좁은 범위의 기능 (VOIP, 오디오 등)을 벗어나 배경 작업을 계속할 수 있도록 설계된 특수 배경 모드가 있습니다. 자세한 내용은 의 장기 실행 태스크 섹션을 참조하십시오.

이제 이러한 백그라운드 모드 중 하나는 "위치"서비스를위한 것입니다. 따라서 이것이 앱의 핵심 기능이라면 적절한 기능에 필수적입니다. location 백그라운드 모드에 등록하면 앱이 백그라운드에서 계속 실행됩니다. 거기에서 위치 업데이트를 모니터링 할 수 있으며 충분한 시간이 경과하면 일부 프로세스가 트리거됩니다. 그러나이 백그라운드 위치 모드가 앱의 필수 기능이 아니라면, 애플은 필요없는 백그라운드 모드를 요청하여 앱을 거부 할 것입니다.


그런데 표준 위치 서비스를 시작하면 장치 배터리가 소모 될 수 있습니다. 배터리를 효율적으로 사용하는 것이 좋습니다 "significant change" location service. 또한 사용자가 상당한 거리 (예 : 킬로미터로 측정)를 이동할 때마다 자동으로 앱을 깨우는 덕분에 다른 셀 타워로 이동하여 발생합니다.

+0

@ 롭 이봐, 감사를 참조하십시오. 네, 위치에 배경 모드를 사용하지 않았습니다. 실제로 위치는 애플리케이션의 핵심 요소입니다. 또한이 응용 프로그램은 내부 사용자/임시 사용자 용입니다. 그런 말로하면 NSTimer를 사용하여 어떻게 움직일 수 있는지에 대한 예를 들어 주거나 ​​빛을 비춰 줄 수 있습니까? – psharma

+0

안녕하세요, @ Rob, 답변 해 주셔서 감사합니다. 이것은 많은 도움이됩니다. 그리고 네, 배터리가 소모되었음을 알고 있습니다. 게다가 중요한 변화를 사용하게 될 것입니다. 지금 내가 실제로 로그에서 테스트하는 데 도움이되는 것은 무엇입니까. 다시 한번 감사드립니다. – psharma

+0

@Rob, 당신이 설명한 방법은 시뮬레이터에서는 작동하지만 기기에서는 작동하지 않습니다. 무엇이 잘못 될 수 있었는지에 대한 아이디어가 있습니까? – nbbk

3

이 시도 :

  • 위치 서비스에 대한 싱글을합니다. NSNotificationCenter

를 통해 AppDelegatewillEnterBackGround, 당신은 알림을 보낼에서는 NSNotification

  • 로 등록 된 후, 사용자의 싱글은 updatingLocation를 시작하고 위치의 데이터를 수신 할 때 서버로 전송합니다.

  • 8

    우리는 위치 문제와 싸우고 있으며 우리를 깨우지 않는 배경 응용 프로그램으로 어려움을 겪고 있기 때문에 몇 가지 메모가 있습니다.

    1. NSTimer는 응용 프로그램이 일시 중지되지 않은 경우에만 유효합니다. 물론, 배경에 있지만 iOS (APN, 위치, ...)에서 알림을 수신 할 수있는 유일한 경우입니다. 결국 BG를 실행하는 동안 타이머가 작동을 멈 춥니 다. 그래서, 당신은 당신을 걷어차 기 위해 BG 모드 중 하나에 의지하고 있습니다.

    2. CLLocationManager.startUpdatingLocation을 사용하는 경우 조금 후에 정보를 얻는 것을 보게됩니다.특히 전화가 이완되고 잠을 잘 때. 이것은 CLLocationManager.pausesLocationUpdatesAutomatically ...라는 기능에 대한 문서화가 잘 안되기 때문입니다.이 기능은 "true"(기본값 설정)로 설정되었을 때 보내는 것을 중지하기로 결정합니다. 이 값을 "false"로 설정하면 위치 업데이트를 계속받을 수 있습니다. 어느 것이 당신의 앱이 당신이 원하는 것을하는지 확실히 알 수 있습니다.

    3. 위에서 언급 한 것처럼 locationManager.didUpdateLocations 콜백을받을 때 backgroundTask를 시작하여 해당 정보를 처리하고 네트워크 데이터를 보내는 동안 응용 프로그램이 작동하도록 유지해야합니다. 하지만 당신은 그것을 이해하는 것 같습니다.

    4. 위치 업데이트를 "기록"하기에 충분히 오래 깨어나서 그렇게 나쁘지 않습니다. 30 분이 소요될 때까지 네트워크 코드를 생성하지 않도록하십시오. 여담 위임 방법`didUpdateToLocation은 다음과 같이

    관련 문제