如何同步对我的网络服务的调用并在 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。

因为我使用的是 AlamoFireSwiftyJSON,所以我创建了一个方法来从我的网络服务中获取记录,如下所示,它使用地图的当前中心(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 在获取后完成