gpt4 book ai didi

ios - 如何在后台使用 MKMapSnapshotter?

转载 作者:行者123 更新时间:2023-11-28 18:51:52 26 4
gpt4 key购买 nike

我有一个应用程序应该在后台获取对象并使用它们的位置数据为它们生成 map 快照。我自然而然地尝试了 MKMapSnapshotter。

事实证明(在对黑色 map 快照感到困惑数周之后)这个工具似乎只有在从主线程调用时才有效,如下所示:

dispatch_async(dispatch_get_main_queue(), ^{
MKMapSnapshotter *snapshotter = [[MKMapSnapshotter alloc] initWithOptions:options];
[snapshotter startWithQueue:dispatch_get_main_queue() completionHandler:^(MKMapSnapshot * _Nullable snapshot, NSError * _Nullable error) {
//Use image here. Image would be completely black if not for the first line of code specifying main thread.
}];
});

这是框架错误吗?

问题:这仅在我的应用程序位于前台时运行。

最佳答案

这对于我正在开发的应用程序来说有点复杂,因为有很多调用为多个缩放级别下载一组 map 图 block ,因此下面的代码可能比您需要的要复杂一些(但表明队列用于快照)。例如,我需要一个 dispatchSemaphore 来避免排队成百上千个并发快照 - 这将它们限制为在线程上捕获大约 25 个并发快照。

此外,我在 Swift 3 中执行此操作,因此 GCD 中可能会有更改,让我可以在向您展示问题时执行此操作。

此处的逻辑是让所有请求在 processQueue 中启动,同时主队列保持畅通,以便 UI 保持事件状态。然后,当最多 25 个请求同时通过信号量门时,它们会通过 snapshotter.start 调用进入快照队列。当一个快照完成时,将启动另一个快照,直到 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
}
})
}

这对我来说非常有用,可以获取多达 5K 的快照来构建 7 缩放级别的离线 map 图像集,而不会阻塞 UI,所以我对代码非常满意。

关于ios - 如何在后台使用 MKMapSnapshotter?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40475345/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com