objective-cでは、メインキューでブロックを実行するように設定したい場合、そのキューに既に存在しているかどうかにかかわらず、マルコ・アーメントのFCUtilitiesからのアプローチ:それはもはや有効だ、スウィフト3世界ではSwift 3のメインキューで安全に効率的にコードを実行する方法
struct Static {
static var onceToken: dispatch_once_t = 0
}
// If we're already on the main thread, just execute the block. Else, dispatch_async(..) it onto the main thread
func onMainThread(block:() ->()) {
dispatch_once(&Static.onceToken) {
dispatch_queue_set_specific(dispatch_get_main_queue(), &Static.onceToken, &Static.onceToken, nil)
}
if (dispatch_get_specific(&Static.onceToken) == &Static.onceToken) {
block()
} else {
dispatch_async(dispatch_get_main_queue(), block)
}
}
:3
https://github.com/marcoarment/FCUtilities/blob/master/FCUtilities/FCBasics.m
プリSWIFT、そのアプローチは、として再生することはできませんでした。私は現在ブロックdispatch_get_specific
がブロックを実行するかディスパッチするかを決定する最も安全な方法だと信じていますが、それをSwift 3に移植することはできません。Swift 3ソリューションとは何でしょうか?
編集: [OK]を、「私はポート新しい構文にすることをどのように行う、これは(いくつかによる)であることをそれを行うための方法を使用?」私もにハングアップなっていたようです実際の答えははるかに簡単であるとき:DispatchQueue.main.async
私はこのコードを理解していません。呼び出し側はブロックが関数が返る前に実行されるかどうかは気にしないので(なぜなら、 'dispatch_async'に渡されるかもしれないので)、なぜ*常に*' dispatch_async'を呼び出すのではないのですか?ここで達成される 'set_specific'の使用は何ですか? –
ブロックをメインキューにプッシュしたい場合は、UIを変更する可能性が高いためです。すでにメインキューに入っている場合は、すでにその処理が行われている可能性があるので、ブロックがインラインで実行されるようにします。メインキューにいなければ、ネットワークからの入力を処理している可能性があり、dispatch_async()に満足しています。要点は、コール・ポイントで、どのケースが当てはまるかを必ずしも知る必要はありませんが、DoTheRightThingにしたいだけです。 'set_specific'は一般的なパターンですが、私はその起源を知らない。おそらく*最善のアプローチ、何らかの尺度で。 – Chris
質問は次のとおりです。なぜこの場合「インライン」で起こるか気になりますか?あなたが 'dispatch_async'を使った場合とは違う振る舞いをします。 'dispatch_sync'に適用するとこのパターンに慣れています。 Appleはこれを避けるべきだと説明しています(ドキュメントでは、「メインキューの作業項目を同期的に実行しようとするとデッドロックが発生する」と明確に言われています)。しかし、私はそれが 'dispatch_async'に適用されたことは今までには見たことがありません。なぜなら、(あなたが明らかに同期していると仮定することはできないので) –