SWIFT - LocationManager looping through multiple times?

后端 未结 2 1107
旧时难觅i
旧时难觅i 2020-12-21 13:33

I have a locationManager function to grab the users current location and posting the name of the city and state. I have a print statement so I can check in my console if eve

相关标签:
2条回答
  • 2020-12-21 13:52

    I had the same problem and Rob's answer didn't do it for me.

    When the location service first starts, the location is updated multiple times regardless of the distanceFilter.

    You might still want the location to be updated and you don't want to lose the location accuracy(which is the whole point of updating location multiple times on start-up), so calling stopUpdatingLocation(or using a local variable) after the first geolocating call isn't the way to go either.

    The most intuitive way is to wrap your geocode call in an @objc function and call the the function with a delay:

    NSObject.cancelPreviousPerformRequests(withTarget: self)
    perform(#selector(myGeocodeFunction(_:)), with: location, afterDelay: 0.5)
    
    0 讨论(0)
  • 2020-12-21 13:56

    I'd first suggest a few things:

    1. Call stopUpdatingLocation before you perform reverseGeocodeLocation.

      You are calling stopUpdatingLocation inside the reverseGeocodeLocation completion handler closure. The problem is that this runs asynchronously, and thus didUpdateLocations may receive additional location updates in the intervening period. And often, when you first start location services, you'll get a number of updates, often with increasing accuracy (e.g. horizontalAccuracy values that are smaller and smaller). If you turn off location services before initiating asynchronous geocode request, you'll minimize this issue.

    2. You can also add add a distanceFilter in viewDidLoad, which will minimize redundant calls to the delegate method:

      locationManager.distanceFilter = 1000
      
    3. You can use your own state variable that checks to see if the reverse geocode process has been initiated. For example:

      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()
          }
      }
      
    0 讨论(0)
提交回复
热议问题