这对于我正在开发的应用程序来说有点复杂,因为有很多调用来下载一组用于多个缩放级别的地图图块,所以下面的代码可能比您需要的要复杂一些(但表明队列适用于快照)。例如,我需要一个 dispatchSemaphore 来避免排队成百上千个并发快照——这将它们限制在线程上捕获的大约 25 个并发快照。
另外,我在 Swift 3 中执行此操作,因此 GCD 中可能会有更改,让我在为您提出问题的同时执行此操作。
这里的逻辑是在 processQueue 中启动所有请求,而主队列保持畅通,以便 UI 保持活动状态。然后,在任何时候最多有 25 个请求通过信号量门,它们通过 snapshotter.start 调用进入 snapshotQueue。当一个快照完成时,会启动另一个快照,直到 processQueue 为空。
unowned let myself = self // Avoid captures in closure
let processQueue = DispatchQueue(label: "processQueue", qos: .userInitiated)
let snapshotQueue = DispatchQueue(label: "snapshotQueue")
var getSnapshotter = DispatchSemaphore(value: 25)
processQueue.async
{
var centerpoint = CLLocationCoordinate2D()
centerpoint.latitude = (topRight.latitude + bottomLeft.latitude) / 2.0
centerpoint.longitude = (topRight.longitude + bottomLeft.longitude) / 2.0
let latitudeDelta = abs(topRight.latitude - bottomLeft.latitude)
let longitudeDelta = abs(topRight.longitude - bottomLeft.longitude)
let mapSpan = MKCoordinateSpanMake(latitudeDelta, longitudeDelta)
var mapRegion = MKCoordinateRegion()
mapRegion.center = centerpoint
mapRegion.span = mapSpan
let options = MKMapSnapshotOptions()
options.region = mapRegion
options.mapType = .standard
options.scale = 1.0
options.size = CGSize(width: 256, height: 256)
myself.getSnapshotter.wait() // Limit the number of concurrent snapshotters since we could invoke very many
let snapshotter = MKMapSnapshotter(options: options)
snapshotter.start(with: myself.snapshotQueue, completionHandler: {snapshot, error in
if error == nil
{
self.saveTile(path: path, tile: snapshot!.image, z: z, x: x, y: y)
// saveTile writes the image out to a file in the mapOverlay file scheme
} else {
print("Error Creating Map Tile: ", error!)
}
if myself.getSnapshotter.signal() == 0
{
// show status as completed (though could be up to 20 snapshots finishing, won't take long at this point
}
})
}
这对我来说可以在不阻塞 UI 的情况下获取多达 5K 的快照以构建 7 缩放级别的离线地图图像集,因此我对代码非常满意。