如何同步对我的网络服务的调用并在 Swift 中的地图上显示数据(使用标记聚类)?
how can I synchronize a call to my webservice and displaying the data on the map (with marker clustering) in Swift?
我正在编写一个在地图上显示很多点的应用程序。我可以将它们全部获取为 json 并将其放在地图上,但是点太多了,所以我考虑实施标记集群。因为我在 Swift 工作,所以我决定使用这个库:https://github.com/ribl/FBAnnotationClusteringSwift
为了避免在我的地图上使用大量数据,我创建了一个后端网络服务,该服务获取当前用户位置和可见半径作为参数。作为答案,它 returns 带有兴趣点 gps 坐标的 JSON。
因为我使用的是 AlamoFire
和 SwiftyJSON
,所以我创建了一个方法来从我的网络服务中获取记录,如下所示,它使用地图的当前中心(lat 和lon)和可见半径:
func fetchRecords(radius: Double, lat: Double, lon: Double){
Alamofire.request(.GET, "http://mywebservice/records", parameters: ["long": lon, "lat": lat, "radius": radius ])
.responseJSON { response in
switch response.result {
case .Success:
self.array.removeAll()
if let jsonData = response.result.value as? [[String: AnyObject]] {
for requestJSON in jsonData {
if let request = SingleRecord.fromJSON(JSON(requestJSON)){
let pinOne = FBAnnotation()
pinOne.coordinate = CLLocationCoordinate2D(latitude: request.latitude, longitude: request.longitude)
self.array.append(pinOne)
}
}
}
self.clusteringManager.addAnnotations(self.array)
case .Failure(let error):
print("SWITCH ERROR")
print(error)
}
}
}
我正在获取当前位置的记录,并且正在为每条记录创建一个 FBAnnotation()
。此外,我将所有点附加到数组“self.array”。到目前为止一切顺利。
我想始终从服务器获取实际数据,所以我决定实现方法 regionDidChangeAnimated
:
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
self.center = mapView.centerCoordinate.latitude.description
self.radius = self.getRadius(mapView)
NSOperationQueue().addOperationWithBlock({
self.fetchRecords(self.radius, lat: self.mapView.centerCoordinate.latitude, lon: self.mapView.centerCoordinate.longitude)
let mapBoundsWidth = Double(self.mapView.bounds.size.width)
let mapRectWidth:Double = self.mapView.visibleMapRect.size.width
let scale:Double = mapBoundsWidth / mapRectWidth
let annotationArray = self.clusteringManager.clusteredAnnotationsWithinMapRect(self.mapView.visibleMapRect, withZoomScale:scale)
self.clusteringManager.displayAnnotations(annotationArray, onMapView:self.mapView)
})
}
我上面所做的是 - 首先 - 获取给定位置的所有当前记录,然后使用 FBAnnotationClusteringSwift
.
中准备好的代码
但是不行,我怀疑是线程的问题,可能是array
还没有填满,或者什么的(?),但是结果如下:
当我打开地图时,我看到:
但是当我稍微移动地图时,标记突然增加:
每一步都一样:
等等。当我放大地图时也会发生同样的情况,即使屏幕中间只剩下一个标记簇 - 每缩放一步它都会增加其数量而不是更改为单个图钉。每次调用 fetchRecords
后,我都试图从数组中删除所有元素,但它也没有帮助。
有谁知道这可能是什么问题?我知道这是一个罕见的话题,但也许有人可以给我任何提示,我将非常感激。谢谢!
在您的获取函数中添加一个完成处理程序
func fetchRecords(radius: Double, lat: Double, lon: Double, completionHandler: (() -> Void)?){
Alamofire.request(.GET, "http://mywebservice/records", parameters: ["long": lon, "lat": lat, "radius": radius ])
.responseJSON { response in
switch response.result {
case .Success:
self.array.removeAll()
if let jsonData = response.result.value as? [[String: AnyObject]] {
for requestJSON in jsonData {
if let request = SingleRecord.fromJSON(JSON(requestJSON)){
let pinOne = FBAnnotation()
pinOne.coordinate = CLLocationCoordinate2D(latitude: request.latitude, longitude: request.longitude)
self.array.append(pinOne)
}
}
}
//TODO: -Clean your data before adding new things
self.clusteringManager.addAnnotations(self.array)
//call the closure after everything is done
completionHandler()
case .Failure(let error):
print("SWITCH ERROR")
print(error)
}
}
}
并在主函数中使用
self.fetchRecords(self.radius, lat: self.mapView.centerCoordinate.latitude, lon: self.mapView.centerCoordinate.longitude) { [weak self] in
let mapBoundsWidth = Double(self?.mapView.bounds.size.width)
let mapRectWidth:Double = self?.mapView.visibleMapRect.size.width
let scale:Double = mapBoundsWidth / mapRectWidth
let annotationArray = self?.clusteringManager.clusteredAnnotationsWithinMapRect(self.mapView.visibleMapRect, withZoomScale:scale)
self?.clusteringManager.displayAnnotations(annotationArray, onMapView:self?.mapView)
}
通过这种方式,您将确保 self?.clusteringManager.displayAnnotations
在获取后完成
我正在编写一个在地图上显示很多点的应用程序。我可以将它们全部获取为 json 并将其放在地图上,但是点太多了,所以我考虑实施标记集群。因为我在 Swift 工作,所以我决定使用这个库:https://github.com/ribl/FBAnnotationClusteringSwift
为了避免在我的地图上使用大量数据,我创建了一个后端网络服务,该服务获取当前用户位置和可见半径作为参数。作为答案,它 returns 带有兴趣点 gps 坐标的 JSON。
因为我使用的是 AlamoFire
和 SwiftyJSON
,所以我创建了一个方法来从我的网络服务中获取记录,如下所示,它使用地图的当前中心(lat 和lon)和可见半径:
func fetchRecords(radius: Double, lat: Double, lon: Double){
Alamofire.request(.GET, "http://mywebservice/records", parameters: ["long": lon, "lat": lat, "radius": radius ])
.responseJSON { response in
switch response.result {
case .Success:
self.array.removeAll()
if let jsonData = response.result.value as? [[String: AnyObject]] {
for requestJSON in jsonData {
if let request = SingleRecord.fromJSON(JSON(requestJSON)){
let pinOne = FBAnnotation()
pinOne.coordinate = CLLocationCoordinate2D(latitude: request.latitude, longitude: request.longitude)
self.array.append(pinOne)
}
}
}
self.clusteringManager.addAnnotations(self.array)
case .Failure(let error):
print("SWITCH ERROR")
print(error)
}
}
}
我正在获取当前位置的记录,并且正在为每条记录创建一个 FBAnnotation()
。此外,我将所有点附加到数组“self.array”。到目前为止一切顺利。
我想始终从服务器获取实际数据,所以我决定实现方法 regionDidChangeAnimated
:
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
self.center = mapView.centerCoordinate.latitude.description
self.radius = self.getRadius(mapView)
NSOperationQueue().addOperationWithBlock({
self.fetchRecords(self.radius, lat: self.mapView.centerCoordinate.latitude, lon: self.mapView.centerCoordinate.longitude)
let mapBoundsWidth = Double(self.mapView.bounds.size.width)
let mapRectWidth:Double = self.mapView.visibleMapRect.size.width
let scale:Double = mapBoundsWidth / mapRectWidth
let annotationArray = self.clusteringManager.clusteredAnnotationsWithinMapRect(self.mapView.visibleMapRect, withZoomScale:scale)
self.clusteringManager.displayAnnotations(annotationArray, onMapView:self.mapView)
})
}
我上面所做的是 - 首先 - 获取给定位置的所有当前记录,然后使用 FBAnnotationClusteringSwift
.
但是不行,我怀疑是线程的问题,可能是array
还没有填满,或者什么的(?),但是结果如下:
当我打开地图时,我看到:
但是当我稍微移动地图时,标记突然增加:
每一步都一样:
等等。当我放大地图时也会发生同样的情况,即使屏幕中间只剩下一个标记簇 - 每缩放一步它都会增加其数量而不是更改为单个图钉。每次调用 fetchRecords
后,我都试图从数组中删除所有元素,但它也没有帮助。
有谁知道这可能是什么问题?我知道这是一个罕见的话题,但也许有人可以给我任何提示,我将非常感激。谢谢!
在您的获取函数中添加一个完成处理程序
func fetchRecords(radius: Double, lat: Double, lon: Double, completionHandler: (() -> Void)?){
Alamofire.request(.GET, "http://mywebservice/records", parameters: ["long": lon, "lat": lat, "radius": radius ])
.responseJSON { response in
switch response.result {
case .Success:
self.array.removeAll()
if let jsonData = response.result.value as? [[String: AnyObject]] {
for requestJSON in jsonData {
if let request = SingleRecord.fromJSON(JSON(requestJSON)){
let pinOne = FBAnnotation()
pinOne.coordinate = CLLocationCoordinate2D(latitude: request.latitude, longitude: request.longitude)
self.array.append(pinOne)
}
}
}
//TODO: -Clean your data before adding new things
self.clusteringManager.addAnnotations(self.array)
//call the closure after everything is done
completionHandler()
case .Failure(let error):
print("SWITCH ERROR")
print(error)
}
}
}
并在主函数中使用
self.fetchRecords(self.radius, lat: self.mapView.centerCoordinate.latitude, lon: self.mapView.centerCoordinate.longitude) { [weak self] in
let mapBoundsWidth = Double(self?.mapView.bounds.size.width)
let mapRectWidth:Double = self?.mapView.visibleMapRect.size.width
let scale:Double = mapBoundsWidth / mapRectWidth
let annotationArray = self?.clusteringManager.clusteredAnnotationsWithinMapRect(self.mapView.visibleMapRect, withZoomScale:scale)
self?.clusteringManager.displayAnnotations(annotationArray, onMapView:self?.mapView)
}
通过这种方式,您将确保 self?.clusteringManager.displayAnnotations
在获取后完成