Wie kann ich meinen Code warten lassen, bis die Aufgabe in DispatchQueue abgeschlossen ist? Benötigt es einen CompletionHandler oder so etwas?
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
}
Ich verwende Xcode 8.2 und schreibe in Swift 3.
Verwenden Sie DispatchGroup
s, um dies zu erreichen. Sie können entweder benachrichtigt werden, wenn die Aufrufe der Gruppe enter()
und leave()
ausgeglichen sind:
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)
}
}
oder du kannst warten (und zurückkehren):
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
}
Hinweis : group.wait()
blockiert die aktuelle Warteschlange (in Ihrem Fall wahrscheinlich die Hauptwarteschlange). Sie müssen also .async in einer anderen Warteschlange (wie im obigen Beispielcode) ausführen, um ein Deadlockzu vermeiden.
In Swift 3 ist kein Abschluss-Handler erforderlich, wenn DispatchQueue
eine Aufgabe abschließt. Außerdem können Sie Ihr Ziel auf verschiedene Weise erreichen
Ein Weg ist das.
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)")
Es wird warten, bis die Schleife beendet ist, aber in diesem Fall wird Ihr Mail-Thread blockiert.
Sie können dasselbe auch so machen
let myGroup = DispatchGroup()
myGroup.enter()
//// Do your task
myGroup.leave() //// When your task completes
myGroup.notify(queue: DispatchQueue.main) {
////// do your remaining work
}
Eine letzte Sache. Wenn Sie completionHandler verwenden möchten, wenn Ihre Aufgabe mit DispatchQueue abgeschlossen ist, können Sie DispatchWorkItem
verwenden.
Hier ist ein Beispiel, wie man DispatchWorkItem
verwendet.
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
}
Versandgruppe verwenden
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
Sie können die Async-Funktion für diese Situationen verwenden. Wenn Sie DispatchGroup()
verwenden, kann manchmal Deadlock vorkommen.
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!)
}
}
}