SWIFT – LocationManager循环多次?

我有一个locationManager函数来获取用户当前位置并发布城市和州的名称。 我有一个打印声明,所以我可以在我的控制台检查一切是否正常工作……事实确实如此。 但是,它打印城市位置3次。 这实际上在我的实际应用程序中引起了一个问题,但这超出了这个问题的范围。

我的function如下:

var usersLocation: String! var locationManager: CLLocationManager! func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { let userLocation: CLLocation = locations[0] CLGeocoder().reverseGeocodeLocation(userLocation) { (placemarks, error) -> Void in if error != nil { print(error) } else { let p = placemarks?.first // ".first" returns the first element in the collection, or nil if its empty // this code above will equal the first element in the placemarks array let city = p?.locality != nil ? p?.locality : "" let state = p?.administrativeArea != nil ? p?.administrativeArea : "" self.navigationBar.title = ("\(city!), \(state!)") self.usersLocation = ("\(city!), \(state!)") self.locationManager.stopUpdatingLocation() print(self.usersLocation) self.refreshPosts() } } } 

所以在我的print(self.usersLocation)中,它将在我的控制台中打印三次。 这是正常的吗?


更新显示视图


 override func viewDidLoad() { super.viewDidLoad() locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest locationManager.requestWhenInUseAuthorization() locationManager.startUpdatingLocation() self.tableView.rowHeight = UITableViewAutomaticDimension self.tableView.estimatedRowHeight = 250.0 } 

我首先建议一些事情:

  1. 在执行reverseGeocodeLocation之前调用reverseGeocodeLocation

    您在reverseGeocodeLocation完成处理程序闭包内调用stopUpdatingLocation 。 问题是这是异步运行的,因此在更新期间, didUpdateLocations可能会收到额外的位置更新。 通常,当您第一次启动位置服务时,您将获得许多更新,通常会提高准确性(例如, horizontalAccuracy精度值越来越小)。 如果在启动异步地理编码请求之前关闭位置服务,则可以最大限度地减少此问题。

  2. 您还可以在viewDidLoad添加一个distanceFilter ,这将最大限度地减少对委托方法的冗余调用:

     locationManager.distanceFilter = 1000 
  3. 您可以使用自己的状态变量来检查反向地理编码过程是否已启动。 例如:

     private var didPerformGeocode = false func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { // if we don't have a valid location, exit guard let location = locations.first where location.horizontalAccuracy >= 0 else { return } // or if we have already searched, return guard !didPerformGeocode else { return } // otherwise, update state variable, stop location services and start geocode didPerformGeocode = true locationManager.stopUpdatingLocation() CLGeocoder().reverseGeocodeLocation(location) { placemarks, error in let placemark = placemarks?.first // if there's an error or no placemark, then exit guard error == nil && placemark != nil else { print(error) return } let city = placemark?.locality ?? "" let state = placemark?.administrativeArea ?? "" self.navigationBar.title = ("\(city), \(state)") self.usersLocation = ("\(city), \(state)") print(self.usersLocation) self.refreshPosts() } } 

我有同样的问题,Rob的回答没有为我做。

当位置服务首次启动时,无论distanceFilter如何,都会多次更新位置。

您可能仍希望更新位置,并且您不希望丢失位置准确性(这是在启动时多次更新位置的整点),因此在第一次调用后调用stopUpdatingLocation(或使用局部变量)地理定位呼叫也不是要走的路。

最直观的方法是将您的地理编码调用包装在@objc函数中并延迟调用该函数:

 NSObject.cancelPreviousPerformRequests(withTarget: self) perform(#selector(myGeocodeFunction(_:)), with: location, afterDelay: 0.5)