问题
I have a Swift app that I am trying to update the location when the app is returned from the background, but it doesn't seem to work when returned from the background.
On launch of the app, I'll get the location just fine. After getting the location I call stopUpdatingLocation() so I don't continue to get the location: locationManager.stopUpdatingLocation()
Then, in my AppDelegate.swift I startUpdatingLocation again:
func applicationWillEnterForeground(application: UIApplication) {
ViewController().locationManager.startUpdatingLocation()
}
This is my code so far:
import UIKit
import CoreLocation
class ViewController: UIViewController, CLLocationManagerDelegate {
var locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!) {
println("Error while updating location " + error.localizedDescription)
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
var userLocation:CLLocation = locations[0] as CLLocation
println("\(userLocation.coordinate.latitude),\(userLocation.coordinate.longitude)")
locationManager.stopUpdatingLocation()
}
}
However, whenever I background the app (click home), and then return to the app the location isn't updated. Any idea what I might be doing wrong here?
回答1:
In applicationWillEnterForeground, the code is creating a new, local instance of ViewController that is never displayed, does not yet have a locationManager created and so has no effect.
It is not referring to the ViewController instance that already exists and is displayed (and has the locationManager instance that was originally started).
Instead, it should get a reference to the existing instance. Assuming ViewController is the root view controller, you could do:
func applicationWillEnterForeground(application: UIApplication) {
if let rvc = window?.rootViewController as? ViewController {
rvc.locationManager.startUpdatingLocation()
}
}
However, it might be better practice to let the
ViewController class itself manage its own behavior. This way, the app delegate doesn't have to find a reference to the view controller's instance and it doesn't directly access the view controller's internal state and ViewController becomes more self-contained.
In addition to the app delegate method applicationWillEnterForeground, it's possible to monitor these events from anywhere using the UIApplicationWillEnterForegroundNotification notification.
In ViewController, you can register and unregister for the notification in (for example) viewWillAppear and viewWillDisappear. When registering, you indicate which method to call for the event and everything is handled inside ViewController (and the code in applicationWillEnterForeground can be removed).
override func viewWillAppear(animated: Bool) {
NSNotificationCenter.defaultCenter().addObserver(
self,
selector: "willEnterForegound",
name: UIApplicationWillEnterForegroundNotification,
object: nil)
}
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(
self,
name: UIApplicationWillEnterForegroundNotification,
object: nil)
}
func willEnterForegound() {
locationManager.startUpdatingLocation()
}
来源:https://stackoverflow.com/questions/28667440/swift-location-not-being-updated-when-returned-from-background