2016-03-22 8 views
11

Ich habe den folgenden Code geschrieben, der über einen Timer verfügt, der jede Minute eine Rückruffunktion aufruft. Wenn die App in den Hintergrund geht, habe ich einen anderen Timer gestartet, der die gleiche Callback-Methode aufruft, aber der Hintergrund-Timer funktioniert nur für drei Minuten.Führen Sie eine Swift 2.0 App für immer im Hintergrund aus, um den Standort auf den Server zu aktualisieren

Ich verstehe, dass Apple Hintergrundaufgaben nur für drei Minuten erlaubt. Meine App ähnelt eher einer Tracking-App, die den Standort des Benutzers jede Minute verfolgt, auch wenn die App im Hintergrund ist. Daher muss ich diese Funktionalität implementieren.

Ich habe gelernt, dass beginBackgroundTaskWithExpirationHandler verwendet werden soll, aber ich weiß nicht, ob meine Implementierung korrekt ist.

Hinweis: Ich habe die erforderlichen Hintergrundmodi in plist toApp registriert für Standortaktualisierungen.

Jeder funktionierende Code oder Links werden sehr geschätzt.

override func viewDidLoad() { 
    super.viewDidLoad() 

    timeInMinutes = 1 * 60 

    self.locationManager.requestAlwaysAuthorization() 

    self.locationManager.requestWhenInUseAuthorization() 

    if CLLocationManager.locationServicesEnabled() { 
     locationManager.delegate = self 
     locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters 
     locationManager.startUpdatingLocation() 
    } 

    var timer = NSTimer.scheduledTimerWithTimeInterval(timeInMinutes, target: self, selector: "updateLocation", userInfo: nil, repeats: true) 
} 

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]){ 
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate 

    self.latitude = locValue.latitude 
    self.longitude = locValue.longitude 

    if UIApplication.sharedApplication().applicationState == .Active { 

    } else { 
     backgroundTaskIdentifier = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({() -> Void in 
      self.backgroundTimer.invalidate() 
      self.backgroundTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: "updateLocation", userInfo: nil, repeats: true) 
     }) 
    } 
} 

func updateLocation() { 
    txtlocationLabel.text = String(n) 
    self.n = self.n+1 

    var timeRemaining = UIApplication.sharedApplication().backgroundTimeRemaining 

    print(timeRemaining) 

    if timeRemaining > 60.0 { 
     self.GeoLogLocation(self.latitude,Longitude: self.longitude) { 
      results in 
      print("View Controller: \(results)") 
      self.CheckResult(String(results)) 
     } 
    } else { 
     if timeRemaining == 0 { 
      UIApplication.sharedApplication().endBackgroundTask(backgroundTaskIdentifier) 
     } 

     backgroundTaskIdentifier2 = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({() -> Void in 
      self.backgroundTimer.invalidate() 
      self.backgroundTimer = NSTimer.scheduledTimerWithTimeInterval(60.0, target: self, selector: "updateLocation", userInfo: nil, repeats: true) 
     }) 
    } 
} 

Antwort

16

Regelmäßige Standortaktualisierungen sind ein bisschen schwierig in IOS.There ist ein guter Thread, der diese diskutiert, können Sie mehr here

lesen

iOS App nach wenigen Minuten beendet wird, unabhängig davon, ob Sie Ihre Zeit läuft oder nicht. Es gibt einen Weg um dies zu tun, ich musste etwas ähnliches tun, wenn Sie eine ionische App schreiben, so dass Sie den Code für diese here auschecken können, dieser Link hat eine schnelle Klasse, die die periodischen Standortaktualisierungen in iOs verwaltet.

Um periodische Standorte im Hintergrund zu erhalten und nicht die Batterie des Geräts zu entleeren, müssen Sie mit der Genauigkeit der Positionsaufzeichnungen spielen, die Genauigkeit des Standortmanagers verringern, der seine gewünschte Genauigkeit auf kCLLocationAccuracyThreeKilometers einstellt, dann Alle 60 Sekunden müssen Sie die Genauigkeit auf kCLLocationAccuracyBest ändern, damit der Stellvertreter eine neue, genaue Standortaktualisierung erhält und die Genauigkeit wieder auf niedrig gesetzt wird. Der Timer muss jedes Mal initialisiert werden, wenn ein Update empfangen wird.

Es gibt auch eine Möglichkeit, die App im Hintergrund zu aktivieren, nachdem sie vom Benutzer getötet wurde. Verwenden Sie den App-Delegierten, um die App auf wesentliche Standortänderungen warten zu lassen, bevor sie beendet werden. Dadurch wird die App im Hintergrund aktiviert, wenn der Standort des Benutzers einen großen Sprung macht (etwa 200 ms). Wenn die App aufwacht, stoppen Sie die Überwachung auf signifikante Änderungen und starten Sie die Standortdienste wie gewohnt neu, um die regelmäßigen Aktualisierungen fortzusetzen.

Hoffe, das hilft.

aktualisieren

In Swift 2 müssen Sie auch:

self.locationManager.allowsBackgroundLocationUpdates = true 
+0

Danke für die Hilfe ... Ich bin ziemlich neu zu Swift ... Ich habe versucht, den Genauigkeitswert alle 60 Sekunden zu ändern, wie Sie sagten ... Ich bekomme immer noch das gleiche Ergebnis (dh die App läuft und aktualisiert den Standort nur für drei Minuten nach dem Hintergrund. – Carey

+1

Hallo, tut mir leid, ich habe vergessen zu erwähnen, und ich glaube, dass dies in Ihrem Code fehlt, müssen Sie auch Hintergrundpositionen in Ihrem Standortmanager aktivieren, etwas in der Art von self.locationManager.allowsBackgroundLocationUpdates = true –

+0

Vielen Dank bro.It hat funktioniert! – Carey

0

Sie Bibliothek für background location tracking verwenden können, Beispiel:

var backgroundLocationManager = BackgroundLocationManager() 

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { 

    backgroundLocationManager.startBackground() { result in 
      if case let .Success(location) = result { 
       LocationLogger().writeLocationToFile(location: location) 
      } 
    } 

    return true 
} 

Es funktioniert, wenn die Anwendung ist getötet oder suspendiert.