CLLocationManager的didUpdateLocations方法被多次调用

4

didUpdateLocations被多次调用,我该如何停止这个方法?我在didUpdateLocations中尝试使用locationManager.stopUpdatingLocation(),但效果不佳。

override func viewDidLoad()
{
    super.viewDidLoad()
    //for Authorisation from the User.
    isAuthorizedtoGetUserLocation()

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

func isAuthorizedtoGetUserLocation() {

    if CLLocationManager.authorizationStatus() != .authorizedWhenInUse     {
        locationManager.requestWhenInUseAuthorization()
    }
}

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    locationManager.stopUpdatingLocation()
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate
    print("locations = \(locValue.latitude) \(locValue.longitude)")

    let camera = GMSCameraPosition.camera(withLatitude: locValue.latitude, longitude: locValue.longitude, zoom: 6.0)
    let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
    self.view = mapView

    // Creates a marker in the center of the map.
    let marker = GMSMarker()
    marker.position = CLLocationCoordinate2D(latitude: locValue.latitude, longitude: locValue.longitude)
    marker.title = "name"
    marker.map = mapView

}

更新后带有错误的代码。
func locationManager( _ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {

    manager.stopUpdatingLocation()
    manager = nil // Here it is giving error "Cannot assign to value: 'manager' is a 'let' constant"

    var newLocation: CLLocation? = locations.last
    var locationAge: TimeInterval? = -(newLocation?.timestamp.timeIntervalSinceNow)!
    if Double(locationAge!) > 5.0 {
        return
    }
    if Double((newLocation?.horizontalAccuracy)!) < 0 {
        return
    }


    //manager = nil
    let locValue:CLLocationCoordinate2D = manager.location!.coordinate
    print("locations = \(locValue.latitude) \(locValue.longitude)")

    let camera = GMSCameraPosition.camera(withLatitude: locValue.latitude, longitude: locValue.longitude, zoom: 6.0)
    let mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
    self.view = mapView

    // Creates a marker in the center of the map.
    let marker = GMSMarker()
    marker.position = CLLocationCoordinate2D(latitude: locValue.latitude, longitude: locValue.longitude)
    marker.title = "name"
    marker.map = mapView

}

1
你怎么确定 startUpdatingLocation() 被调用了多次?从你的代码看,它应该只在每次加载视图时被调用一次。 - dylanthelion
在这种情况下,这是预期的行为。该方法的调用频率由kCLLocationAccuracy确定。请参考@anbu的答案以了解如何设置它。基本上,您的精度越高,委托中该方法被调用的频率就越高,您的手机就会使用更多的功率(GPS会非常快地消耗电池)。 - dylanthelion
请在您的问题中仅包含相关代码。让人们阅读与您提问无关的代码(例如,所有地图和标记代码)是不尊重他人的行为。 - Ashley Mills
3个回答

3

你需要将CLLocation manager的distanceFilter属性设置为以下值:

/* Notify changes when device has moved x meters.
 * Default value is kCLDistanceFilterNone: all movements are reported.
 */
self.locationManager.distanceFilter = 10.0f; // you can change as per your require ment

2
将属性distanceFilter设置为常量距离最大值CLLocationDistanceMax,表示仅在设备移动了相当大的距离后才会触发新的更新。原始答案:最初的回答。

-3
另一种方法是这样的。 我的应用程序需要在位置改变时上传位置。 即使我像这样声明距离过滤器:

locationManager.distanceFilter = 300

当您首次创建CLLocationManager或调用startUpdatingLocation()时,它可能会被多次调用。

因此,我将它们放入任务队列中,如下所示:

     if let locationUploadTask = self.locationTask { // if there is a task waiting, cancel it 
            locationUploadTask.cancel()
        }

     self.locationTask = DispatchWorkItem { //create a new task for upload
            //do your task
        }

     DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1, execute: self.locationTask!) //execute the task 1 second after

这段代码强制你的代码等待1秒钟。如果在一秒钟内有新的位置更新,则取消当前任务,重新开始等待1秒钟。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接