Swift 如何从Web服务器为MapView加载最佳位置
我在网络数据库中有2000个位置,用户应该能够在地图上选择。我可以要求web数据库只提供来自当前位置的特定数量的位置 为了使一切顺利和优雅,我首先实例化MKMapView,启动CLLocationManager,并等待得到didUpdateLocations。然后,我将尝试使用完成处理程序从数据库中获取数据 我应该吗 a) 一次获取所有数据 b) 将数据分成小块或小块 最好的方法是什么Swift 如何从Web服务器为MapView加载最佳位置,swift,mkmapview,Swift,Mkmapview,我在网络数据库中有2000个位置,用户应该能够在地图上选择。我可以要求web数据库只提供来自当前位置的特定数量的位置 为了使一切顺利和优雅,我首先实例化MKMapView,启动CLLocationManager,并等待得到didUpdateLocations。然后,我将尝试使用完成处理程序从数据库中获取数据 我应该吗 a) 一次获取所有数据 b) 将数据分成小块或小块 最好的方法是什么 func locationManager(manager: CLLocationManager, didUpd
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)
})
})
}
首先,您应该考虑在MKMapView上是否同时安装2000个注释。也许你应该试着只恢复你正在展示的地图中适合的位置 之后,在代码中,每次调用
didUpdateLocations
时都要添加注释。?是否在其他地方删除旧的批注?。如果注释没有更改,并且位于地图上,则不应再次添加它们
我认为一个好的方法应该是:
1.-第一次调用didUpdateLocations
:要求web服务提供距离等于地图显示区域两倍的注释。将该位置另存为locationOrigin,将该距离另存为distanceOrigin
2.-下次调用didUpdateLocations
:如果从当前位置移动到locationOrigin的距离等于distanceOrigin的一半。您应该再次查询web服务,更新“源”变量,并仅向mapView添加新注释
3.-如果调用了
regionWillChange
(MKMapViewDelegate
):用户正在缩放、移动地图或旋转设备。。。。简单的方法是重新加载注释,就像我们在第1步一样。一种更智能的方法是添加一个手势识别器来检测用户是否在放大(在这种情况下,注释不会改变),或者缩小或移动(注释可能会改变)一次获取所有数据是不可伸缩的。您可以使用2000个条目使其及时工作,但是如果数据集增长了怎么办?你能应付3000英镑吗?5000? 10000条注释
以块的形式获取数据,只返回地图居中位置附近的条目,并在用户在地图上移动时显示这些条目更有意义。但是,这种方法非常慢,因为用户拖动地图和屏幕上出现的注释之间通常有很长的延迟(网络请求本质上很慢)
因此,为获得良好的用户体验,推荐的方法是在本地缓存结果。如果您有一个本地数据库(例如核心数据),或者您可以使用NSCache
执行此操作
使用这种方法,当用户在地图上移动时,您将向服务器发送新的请求,但返回的结果量可以限制为20、50或100(这可以在响应速度非常快的情况下获得最高的数据量)
接下来,您将在地图上呈现缓存结果中的所有注释,因此注释的数量将随着用户在地图上的移动而增加
来自的家伙们有一个很好的视频来解释这种方法:虽然你不需要使用他们的移动数据库(领域),但你可以了解应用程序的架构和设计。在当前用户位置附近分块加载它们,如果用户缩小加载另一个块,如果用户移动地图加载另一个块等等。这样,如果您的注释越来越像1M注释,那么您的应用程序将可以更好地扩展。我实际上已经编写了一个应用程序,它可以在MKMapView上放置7000个注释,而不会出现性能问题。。。这是在iPad1上实现的。你真的不必担心地图
我能想到的唯一限制因素是网络通话需要多长时间,以及这是否会成为一个问题。在我的例子中,我从联系人数据库中提取地址,对它们进行地理编码,然后将lat long存储在核心数据中。是的,对7000个地址进行地理编码需要花费很长时间,但一旦你有了lat long,将它们放在地图上就很容易了,地图代码可以很好地处理它……这是一次性的吗?换句话说,在第一次加载应用程序后,您是否会将其全部存储在本地?2000条注释就可以了。与UITableView非常相似。地图不会浪费处理当前不可见注释的周期。@DanielT。我不是在考虑MapView的性能,而是在考虑网络性能。如果他只想展示50个,也许他不需要恢复2000个位置。顺便说一句,很高兴知道你可以有一个超过7000注释的地图。