iOS
DispatchGroup
Zoeken…
Invoering
Invoering
Stel dat je meerdere threads hebt. Elke thread voert één taak uit. U wilt een melding ontvangen op de mainThread OF een andere thread, wanneer alle taak-threads zijn voltooid.
De eenvoudigste oplossing voor een dergelijk probleem is een DispatchGroup
.
Wanneer u een DispatchGroup
, enter
u voor elke aanvraag de groep in en voor elke voltooide aanvraag leave
de groep.
Wanneer er geen aanvragen meer in de groep zijn, wordt u hiervan op de notify
(gemeld).
Gebruik:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let dispatchGroup = DispatchGroup() //Create a group for the tasks.
let session: URLSession = URLSession.shared
dispatchGroup.enter() //Enter the group for the first task.
let firstTask = session.dataTask(with: URLRequest(url: URL(string: "https://stackoverflow.com")!)) { (data, response, error) in
//Process Response..
dispatchGroup.leave() //Leave the group for the first task.
}
dispatchGroup.enter() //Enter the group for the second task.
let secondTask = session.dataTask(with: URLRequest(url: URL(string: "https://google.ca")!)) { (data, response, error) in
//Process Response..
dispatchGroup.leave() //Leave the group for the second task.
}
//Get notified on the main thread/queue.. when ALL of the tasks above has been completed.
dispatchGroup.notify(queue: DispatchQueue.main) {
print("Every task is complete")
}
//Start the tasks.
firstTask.resume()
secondTask.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Met het bovenstaande hoeft u niet oneindig te wait
tot alle taken zijn voltooid. U kunt een lader weergeven VOORDAT alle taken zijn gestart en de lader sluiten NADAT alle taken zijn voltooid. Op deze manier wordt uw hoofdthread niet geblokkeerd en blijft uw code schoon.
Stel nu dat u ook wilt dat de taken worden ordered
of voeg hun antwoorden achtereenvolgens toe aan een array. Je zou het volgende kunnen doen:
import UIKit
//Locking mechanism..
func synchronized(_ lock: AnyObject, closure: () -> Void) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
class ViewController: UIViewController {
let lock = NSObject() //Object to lock on.
var responseArray = Array<Data?>() //Array of responses.
override func viewDidLoad() {
super.viewDidLoad()
let dispatchGroup = DispatchGroup()
let session: URLSession = URLSession.shared
dispatchGroup.enter() //Enter the group for the first task.
let firstTask = session.dataTask(with: URLRequest(url: URL(string: "https://stackoverflow.com")!)) { (data, response, error) in
//Process Response..
synchronized(self.lock, closure: { () -> Void in
self.responseArray[0] = data ?? nil
})
dispatchGroup.leave() //Leave the group for the first task.
}
dispatchGroup.enter() //Enter the group for the second task.
let secondTask = session.dataTask(with: URLRequest(url: URL(string: "https://google.ca")!)) { (data, response, error) in
//Process Response..
synchronized(self.lock, closure: { () -> Void in
self.responseArray[1] = data ?? nil
})
dispatchGroup.leave() //Leave the group for the second task.
}
//Get notified on the main thread.. when ALL of the requests above has been completed.
dispatchGroup.notify(queue: DispatchQueue.main) {
print("Every task is complete..")
for i in 0..<self.responseArray.count {
if self.responseArray[i] == nil {
print("Request #\(i) Failed.\n")
}
else {
print("Request #\(i) Succeeded.\n")
}
}
}
//Two tasks added to the array. Responses are assumed nil until they complete.
self.responseArray.append(nil)
self.responseArray.append(nil)
//Start the tasks.
firstTask.resume()
secondTask.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Notes
Elk item moet een exit hebben in een DispatchGroup
. Als je vergeet te leave
na entering
, ben je jezelf aan het instellen. U ontvangt NOOIT een melding wanneer de taken zijn voltooid.
Het aantal enter
moet gelijk zijn aan het aantal leave
.