如何从Webserver最佳地加载MapView的位置

时间:2015-10-03 13:13:55

标签: swift mkmapview

我在网络数据库中有2000个位置,用户应该可以在地图上选择这些位置。我可以要求网络数据库只给我一些来自当前位置的位置。

为了让一切顺利和优雅我首先实例化MKMapView,启动CLLocationManager并等到我得到didUpdateLocations。然后我会尝试从具有完成处理程序的数据库中获取数据。

我应该

a)立即获取所有数据

b)以小块或块的形式获取数据?

最好的方式是什么?

func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    self.gotoCurrentLocation()
    if let userLocation = manager.location {
        GroundHelper.getAllGroundLocations(userLocation) { self.handleWaypoints($0!) }
    }
}

private func handleWaypoints(grounds: [Ground]) {
    mapView.addAnnotations(grounds)
}

// MARK: - Helper Methods

typealias GPXCompletionHandler = ([Ground]?) -> Void

class func getAllGroundLocations(userlocation: CLLocation, completionHandler: GPXCompletionHandler)  {

    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
    dispatch_async(dispatch_get_global_queue(priority, 0), { ()->() in
        var results = RestApiManager.sharedInstance.getGPS(userlocation, limit: 50)

        // return first 50 results
        dispatch_async(dispatch_get_main_queue(), {

            var grounds = [Ground]()
            for result in results {
                let (_,jsonGround) = result
                let ground = Ground(json:jsonGround)
                grounds.append(ground)
            }
            completionHandler(grounds)
        })

        // get the rest
        results = RestApiManager.sharedInstance.getGPS(userlocation)

        // return them
        dispatch_async(dispatch_get_main_queue(), {

            var grounds = [Ground]()
            for result in results {
                let (_,jsonGround) = result
                let ground = Ground(json:jsonGround)
                grounds.append(ground)
            }
            completionHandler(grounds)

        })
    })
}

4 个答案:

答案 0 :(得分:2)

一次获取所有数据是不可扩展的。您可以使用2000个条目及时工作,但如果数据集增长怎么办?你能处理3000吗? 5000? 10000注释?

以数据块的形式获取数据,仅返回地图所在位置附近的条目,并在用户围绕地图移动时显示这些条目更有意义。但是,这种方法非常慢,因为用户拖动地图和屏幕上出现的注释之间通常会有很长的延迟(网络请求本质上很慢)。

因此,推荐的用户体验方法是在本地缓存结果。如果您有本地数据库(例如Core Data),或者您可以使用NSCache执行此操作,则可以执行此操作。

使用这种方法,当用户在地图上移动时,您将使用新请求命中服务器,但返回的结果数量可以限制为20,50或100(这样可以获得最高数据量)非常敏感。)

接下来,您将在地图上渲染缓存结果中的所有注释,因此当用户在地图上移动时,注释的数量会增加。

来自http://realm.io的人有一个非常好的视频解释了这种方法:https://www.youtube.com/watch?v=hNDNXECD84c虽然您不需要使用他们的移动数据库(Realm),但您可以了解应用程序架构和设计。

答案 1 :(得分:0)

首先,您应该考虑在MKMapView上是否同时支持2000个注释。也许你应该尝试只恢复你所呈现的地图中的位置。

之后,在您的代码中,每次调用didUpdateLocations时都会添加注释。 ¿您是否在其他任何地方删除了较旧的注释?如果注释没有改变,并且在地图上,则不应再次添加注释。

我认为一个好方法应该是:

1.-第一次调用didUpdateLocations:向您的Web服务询问注释,其距离等于显示地图的区域的两倍。将该位置保存为locationOrigin,将该距离保存为distanceOrigin

2.-下一次调用didUpdateLocations:如果从当前位置移动到locationOrigin的距离等于distanceOrigin的一半。您应该再次查询Web服务,更新“Origin”变量,并仅将新注释添加到mapView。

3.-如果regionWillChange被调用(MKMapViewDelegate):用户正在缩放,移动地图或旋转设备....简单的方法是重新加载注释,就好像我们一样步骤1.更智能的方法是添加手势识别器以检测用户是否放大(在这种情况下注释不会更改),或缩小或移动(注释可能会更改)

答案 2 :(得分:0)

如果用户缩小加载另一个块,如果用户移动地图加载另一个块等,则将它们加载到当前用户位置附近的块中。这样,如果您的注释变得越来越像1M注释,您的应用将更好地扩展。

答案 3 :(得分:0)

我实际上已经编写了一个可以在MKMapView上放置7000个注释但没有性能问题的应用程序......而且这个应用程序在iPad上1.你真的不需要担心地图。

我能想到的唯一限制因素是网络呼叫需要多长时间以及这是否会成为问题。在我的例子中,我从联系人数据库中提取地址,对它们进行地理编码,然后将lat-long存储在核心数据中。是地理编码7000地址需要永远,但是一旦你有了lat-longs将它们放在地图上很简单,地图代码可以很好地处理它......