SWIFT-LocationManager多次循环通过



我有一个locationManager功能,可以获取用户的当前位置,并发布城市和州的名称。我有一份打印声明,这样我就可以在控制台中检查一切是否正常。。。确实如此。然而,它打印了三次城市位置。这实际上在我的实际应用程序中引起了一个问题,但这超出了这个问题的重点。

我的功能如下:

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()
        }
    }
}

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


更新显示VIEWDIDLOAD


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之前,请先调用stopUpdatingLocation

    您正在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的回答对我没有帮助。

当定位服务首次启动时,无论距离过滤器如何,位置都会更新多次。

您可能仍然希望更新位置,并且不想失去位置准确性(这是启动时多次更新位置的全部意义),因此在第一次地理定位调用后调用stopUpdatingLocation(或使用本地变量)也不是一种方法。

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

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

相关内容

  • 没有找到相关文章

最新更新