DispatchQueueのタスクが終了するまでコードを待機させるにはどうすればよいですか。 CompletionHandlerか何かが必要ですか?
func myFunction() {
var a: Int?
DispatchQueue.main.async {
var b: Int = 3
a = b
}
// wait until the task finishes, then print
print(a) // - this will contain nil, of course, because it
// will execute before the code above
}
私はXcode 8.2を使用しており、Swift 3で書いています。
これを実現するにはDispatchGroup
sを使用してください。グループのenter()
とleave()
の呼び出しが均衡したときに通知を受けることができます。
func myFunction() {
var a: Int?
let group = DispatchGroup()
group.enter()
DispatchQueue.main.async {
a = 1
group.leave()
}
// does not wait. But the code in notify() gets run
// after enter() and leave() calls are balanced
group.notify(queue: .main) {
print(a)
}
}
または、待つ(そして戻る)こともできます。
func myFunction() -> Int? {
var a: Int?
let group = DispatchGroup()
group.enter()
// avoid deadlocks by not using .main queue here
DispatchQueue.global(attributes: .qosDefault).async {
a = 1
group.leave()
}
// wait ...
group.wait()
// ... and return as soon as "a" has a value
return a
}
注:group.wait()
は現在のキュー(おそらくあなたの場合はメインキュー)をブロックするので、(上記のサンプルコードのように)別のキューでdispatch.async
を実行する必要があります。 デッドロックを回避する。
Swift 3では、DispatchQueue
が1つのタスクを終了するときに完了ハンドラーは不要です。さらに、あなたはさまざまな方法であなたの目標を達成することができます
一つの方法はこれです。
var a: Int?
let queue = DispatchQueue(label: "com.app.queue")
queue.sync {
for i in 0..<10 {
print("Ⓜ️" , i)
a = i
}
}
print("After Queue \(a)")
ループが終了するまで待ちますが、この場合あなたのメールスレッドはブロックします。
これと同じことができます
let myGroup = DispatchGroup()
myGroup.enter()
//// Do your task
myGroup.leave() //// When your task completes
myGroup.notify(queue: DispatchQueue.main) {
////// do your remaining work
}
最後に一つだけ。タスクがDispatchQueueを使用して完了したときにcompletionHandlerを使用したい場合は、DispatchWorkItem
を使用できます。
これはDispatchWorkItem
の使い方の例です。
let workItem = DispatchWorkItem {
// Do something
}
let queue = DispatchQueue.global()
queue.async {
workItem.perform()
}
workItem.notify(queue: DispatchQueue.main) {
// Here you can notify you Main thread
}
派遣団を利用する
dispatchGroup.enter()
FirstOperation(completion: { _ in
dispatchGroup.leave()
})
dispatchGroup.enter()
SecondOperation(completion: { _ in
dispatchGroup.leave()
})
dispatchGroup.wait() //Waits here on this thread until the two operations complete executing.
Swift 4
これらの状況では非同期機能を使用できます。あなたがDispatchGroup()
を使うとき、時々デッドロックが起こるかもしれません。
var a: Int?
@objc func myFunction(completion:@escaping (Bool) -> () ) {
DispatchQueue.main.async {
let b: Int = 3
a = b
completion(true)
}
}
override func viewDidLoad() {
super.viewDidLoad()
myFunction { (status) in
if status {
print(self.a!)
}
}
}