これは、複数のズームレベルのマップタイルセットをダウンロードするための呼び出しがたくさんあるので、私が取り組んでいるアプリにとっては少し複雑だったので、以下のコードは必要以上に複雑ですそのキューはスナップショット作成のために機能します)。たとえば、ディスパッチセマフォーを使用すると、数百から数千もの同時スナップショットをキューに入れないようにする必要があります。これにより、スレッドでキャプチャされているスナップショットが約25個に制限されます。
また、私はSwift 3でこれをやっていますので、あなたに問題を提示しながらGCDに変更を加えることができます。
ロジックは、メインキューがブロック解除されたままで、UIがアクティブのままである間に、すべてのリクエストをprocessQueueで開始することです。次に、最大25個のリクエストがいつでもセマフォゲートを通過するので、snapshotter.startコールを介してsnapshotQueueに入ります。 1つのスナップショットが終了すると、もう1つは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をブロックすることなく、7ズームレベルオフライン地図画像セットを構築するために5Kのスナップショットを取得して私の作品、私はコードでかなり快適です。
フォアグラウンドにする必要があるので、私は[UIApplication.shared.isIdleTimerDisabled = true]というコマンドを使用します。完了したら、必ずfalseに設定してください。 –
うわー、印象的ですね。私はこのような高度なキューイングに精通していません。この解決策のいくつかの形式を試してみてください。 – TealShift
私はApple Watchからトレーニングデータを引き出しているので、残念ながらフォアグラウンドが必要です.BG処理を中止する唯一の方法はこのダム機能です。 :/ – TealShift