最小化使用 LocationManager 时对我的服务器发出的 HTTP 请求
Minimize HTTP requests made to my server when using LocationManager
在下面的代码中,我使用 LocationManager 获取用户的当前邮政编码,然后向我自己的服务器发出 HTTP 请求,以根据用户的邮政编码获取一些数据。我的问题是我下面的代码每次调用 locationManager
时都会发出 HTTP 请求,通常每次调用三次。理想情况下,我只想在找到最后一个地标后发出 HTTP 请求。
如何最大限度地减少对我自己的服务器发出的 HTTP 请求?
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)-> Void in
if error != nil {
//AlertView to show the ERROR message
}
if placemarks!.count > 0 {
let placemark = placemarks![0]
var zipCode = placemark.postalCode ?? ""
makeHTTPRequest(zipCode) // this is called 3 times
self.locationManager.stopUpdatingLocation()
}else{
print("No placemarks found.")
}
})
}
您的代码的问题在于,在您执行 self.locationManager.stopUpdatingLocation()
时,可能有多个对 locationManager(_:didUpdateLocations:)
的调用堆积起来。要解决这个问题:
- 定义一个全局变量
var didFindZipCode: Bool = false
。
- 在检查地标数量的 if 块的开头添加
guard didFindZipCode == false else { return }
。
- 在 guard 语句之后设置
didFindZipCode = true
。
只要记得将 didFindZipCode
设置为 false
,每当您想再次开始更新位置时。
问题是您的 CLGeocoder
方法 returns 是异步的,到它 returns 一个值时,您的位置管理器已经触发了多次。因此,只需在位置管理器第一次调用后停止更新位置,然后进行异步工作。
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else {
return
}
// handle async work
CLGeocoder().reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
if let error = error {
// alert with error
} else if let placemarks = placemarks,
placemarks.count > 0 {
let placemark = placemarks[0]
var zipCode = placemark.postalCode ?? ""
makeHTTPRequest(zipCode)
} else {
print("No placemarks found.")
}
})
locationManager.stopUpdatingLocation() // stop updating
}
顺便说一句,链接 if-else
语句也是一种很好的做法。如果您以 if
开头,您几乎应该总是在其后跟一个 else
,而不是在其后跟一个新的 if
块。
在下面的代码中,我使用 LocationManager 获取用户的当前邮政编码,然后向我自己的服务器发出 HTTP 请求,以根据用户的邮政编码获取一些数据。我的问题是我下面的代码每次调用 locationManager
时都会发出 HTTP 请求,通常每次调用三次。理想情况下,我只想在找到最后一个地标后发出 HTTP 请求。
如何最大限度地减少对我自己的服务器发出的 HTTP 请求?
override func viewDidLoad() {
super.viewDidLoad()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)-> Void in
if error != nil {
//AlertView to show the ERROR message
}
if placemarks!.count > 0 {
let placemark = placemarks![0]
var zipCode = placemark.postalCode ?? ""
makeHTTPRequest(zipCode) // this is called 3 times
self.locationManager.stopUpdatingLocation()
}else{
print("No placemarks found.")
}
})
}
您的代码的问题在于,在您执行 self.locationManager.stopUpdatingLocation()
时,可能有多个对 locationManager(_:didUpdateLocations:)
的调用堆积起来。要解决这个问题:
- 定义一个全局变量
var didFindZipCode: Bool = false
。 - 在检查地标数量的 if 块的开头添加
guard didFindZipCode == false else { return }
。 - 在 guard 语句之后设置
didFindZipCode = true
。
只要记得将 didFindZipCode
设置为 false
,每当您想再次开始更新位置时。
问题是您的 CLGeocoder
方法 returns 是异步的,到它 returns 一个值时,您的位置管理器已经触发了多次。因此,只需在位置管理器第一次调用后停止更新位置,然后进行异步工作。
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.last else {
return
}
// handle async work
CLGeocoder().reverseGeocodeLocation(location, completionHandler: { (placemarks, error) -> Void in
if let error = error {
// alert with error
} else if let placemarks = placemarks,
placemarks.count > 0 {
let placemark = placemarks[0]
var zipCode = placemark.postalCode ?? ""
makeHTTPRequest(zipCode)
} else {
print("No placemarks found.")
}
})
locationManager.stopUpdatingLocation() // stop updating
}
顺便说一句,链接 if-else
语句也是一种很好的做法。如果您以 if
开头,您几乎应该总是在其后跟一个 else
,而不是在其后跟一个新的 if
块。