我有一个列表,其中填充了来自 API 的数据。所以基本上过程是这样的:
当用户打开应用程序时,我会执行以下操作:
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.distanceFilter = 20
locationManager.startUpdatingLocation()
}
然后在我的 func locationManager(manager: CLLocationManager, didUpdateLocationslocations: [CLLocation])
中,我调用 API 来获取数据。
但问题是 func locationManager(manager: CLLocationManager, didUpdateLocationslocations: [CLLocation])
有时最多可以调用 5-6 次,因此会有大量 API 调用,如果我只获得一个位置,很有可能我获得的位置可能远离用户。
有什么想法可以解决这个问题吗?我基本上想要最好的位置并进行尽可能少的 API 调用,最好是这样。
最佳答案
基本上,如果您想避免在 func locationManager(manager: CLLocationManager, didUpdateLocationslocations: [CLLocation])
处调用 API,您需要考虑一些控件:
- 创建接收位置之间的时间间隔
- “改进”您的
horizontalAccuracy
和distanceFilter
值
请记住,您始终需要避免:
- 避免零位置
- 位置无效
- 位置无效
- 位置无序
- 缓存位置(在启动 locationManager 之前)
代码示例:
protocol MyLocationManagerDelegate {
func locationControllerDidUpdateLocation(location: CLLocation)
}
final class MyLocationManager: NSObject, CLLocationManagerDelegate {
var oldLocation: CLLocation?
let kTimeFilter = Double(10) //avoid locations for each kTimeFilter seconds
let kValidDistanceToOldLocation = Double(100) //avoid location less than kValidDistanceToOldLocation meters
var startDate: NSDate?
var delegate: MyLocationManagerDelegate?
func isValidLocation(newLocation newLocation: CLLocation?, oldLocation: CLLocation?) -> Bool {
// avoid nil locations
if newLocation == nil {
return false
}
//avoid invalid locations
if newLocation!.coordinate.latitude == 0 || newLocation!.coordinate.longitude == 0 {
return false
}
//avoid invalid locations
if (newLocation!.horizontalAccuracy < 0){
return false
}
if oldLocation != nil {
let distance = newLocation!.distanceFromLocation(oldLocation!)
if fabs(distance) < kValidDistanceToOldLocation {
return false
}
//avoid out-of-order location.
let secondsSinceLastPoint = newLocation!.timestamp.timeIntervalSinceDate(oldLocation!.timestamp)
if secondsSinceLastPoint < 0 || secondsSinceLastPoint < kTimeFilter {
return false
}
}
//avoid cached locations (before you start the locationManager)
let secondsSinceManagerStarted = newLocation!.timestamp.timeIntervalSinceDate(startDate!)
if secondsSinceManagerStarted < 0 {
return false
}
return true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let newLocation = locations.last
if isValidLocation(newLocation: newLocation, oldLocation:oldLocation) || oldLocation == nil {
self.delegate?.locationControllerDidUpdateLocation(newLocation!)
oldLocation = newLocation
}
}
}
class ViewController: UIViewController, MyLocationManagerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let location = MyLocationManager()
location.delegate = self
}
func locationControllerDidUpdateLocation(location: CLLocation) {
//Api Call
}
}
关于swift - 位置管理器位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39212373/