Comment utiliser le threading en quick?
dispatchOnMainThread:^{
NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}];
Beaucoup a été modernisé dans Swift 3.0. Exécuter quelque chose sur le fil de fond ressemble à ceci:
DispatchQueue.global(qos: .background).async {
print("This is run on the background queue")
DispatchQueue.main.async {
print("This is run on the main queue, after the previous code in outer block")
}
}
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
print("This is run on the background queue")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print("This is run on the main queue, after the previous code in outer block")
})
})
À partir de Swift 1.1 Apple ne supportait pas la syntaxe ci-dessus sans quelques modifications. Passer QOS_CLASS_BACKGROUND
ne fonctionnait pas, utilisez plutôt Int(QOS_CLASS_BACKGROUND.value)
.
Pour plus d'informations, voir Documentation d'Apple
La meilleure pratique consiste à définir une fonction réutilisable accessible plusieurs fois.
par exemple. quelque part comme AppDelegate.Swift en tant que fonction globale.
func backgroundThread(_ delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)) {
background?()
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue()) {
completion?()
}
}
}
Remarque: dans Swift 2.0, remplacez QOS_CLASS_USER_INITIATED.value ci-dessus par QOS_CLASS_USER_INITIATED.rawValue à la place
A. Pour exécuter un processus en arrière-plan avec un délai de 3 secondes:
backgroundThread(3.0, background: {
// Your background function here
})
B. Pour exécuter un processus en arrière-plan, exécutez une complétion au premier plan:
backgroundThread(background: {
// Your function here to run in the background
},
completion: {
// A function to run in the foreground when the background thread is complete
})
C. Pour retarder de 3 secondes - notez l’utilisation du paramètre de complétion sans paramètre de fond:
backgroundThread(3.0, completion: {
// Your delayed function here to be run in the foreground
})
La réponse de Dan Beaulieu dans Swift5 (fonctionne également depuis Swift 3.0.1).
extension DispatchQueue {
static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
DispatchQueue.global(qos: .background).async {
background?()
if let completion = completion {
DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
completion()
})
}
}
}
}
DispatchQueue.background(delay: 3.0, background: {
// do something in background
}, completion: {
// when background job finishes, wait 3 seconds and do something in main thread
})
DispatchQueue.background(background: {
// do something in background
}, completion:{
// when background job finished, do something in main thread
})
DispatchQueue.background(delay: 3.0, completion:{
// do something in main thread after 3 seconds
})
Swift 3 utilise la nouvelle classe DispatchQueue
pour gérer les files d'attente et les threads. Pour exécuter quelque chose sur le fil d’arrière-plan que vous utiliseriez:
let backgroundQueue = DispatchQueue(label: "com.app.queue", qos: .background)
backgroundQueue.async {
print("Run on background thread")
}
Ou si vous voulez quelque chose en deux lignes de code:
DispatchQueue.global(qos: .background).async {
print("Run on background thread")
DispatchQueue.main.async {
print("We finished that.")
// only back on the main thread, may you access UI:
label.text = "Done."
}
}
Vous pouvez également obtenir des informations détaillées sur GDC dans Swift 3 in ce tutoriel .
De le tutoriel de Jameson Quave
Swift 2
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
//All stuff here
})
Dans Swift 4.2 et Xcode 10.1
Nous avons trois types de files d'attente:
1. File d'attente principale: La file d'attente principale est une file d'attente série créée par le système et associée au thread principal de l'application.
2. File d'attente globale: La file d'attente globale est une file d'attente simultanée que nous pouvons demander en ce qui concerne la priorité des tâches.
3. Files d'attente personnalisées: peuvent être créées par l'utilisateur. Les files d'attente simultanées personnalisées sont toujours mappées dans l'une des files d'attente globales en spécifiant une propriété de qualité de service (QoS).
DispatchQueue.main//Main thread
DispatchQueue.global(qos: .userInitiated)// High Priority
DispatchQueue.global(qos: .userInteractive)//High Priority (Little Higher than userInitiated)
DispatchQueue.global(qos: .background)//Lowest Priority
DispatchQueue.global(qos: .default)//Normal Priority (after High but before Low)
DispatchQueue.global(qos: .utility)//Low Priority
DispatchQueue.global(qos: .unspecified)//Absence of Quality
Toutes ces files d'attente peuvent être exécutées de deux manières
1. Exécution synchrone
2. Exécution asynchrone
DispatchQueue.global(qos: .background).async {
// do your job here
DispatchQueue.main.async {
// update ui here
}
}
//Perform some task and update UI immediately.
DispatchQueue.global(qos: .userInitiated).async {
// Perform task
DispatchQueue.main.async {
// Update UI
self.tableView.reloadData()
}
}
//To call or execute function after some time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}
//If you want to do changes in UI use this
DispatchQueue.main.async(execute: {
//Update UI
self.tableView.reloadData()
})
Depuis AppCoda: https://www.appcoda.com/grand-central-dispatch/
//This will print synchronously means, it will print 1-9 & 100-109
func simpleQueues() {
let queue = DispatchQueue(label: "com.appcoda.myqueue")
queue.sync {
for i in 0..<10 {
print("????", i)
}
}
for i in 100..<110 {
print("Ⓜ️", i)
}
}
//This will print asynchronously
func simpleQueues() {
let queue = DispatchQueue(label: "com.appcoda.myqueue")
queue.async {
for i in 0..<10 {
print("????", i)
}
}
for i in 100..<110 {
print("Ⓜ️", i)
}
}
Vous devez séparer les modifications que vous souhaitez exécuter en arrière-plan des mises à jour que vous souhaitez exécuter sur l'interface utilisateur:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
// do your task
dispatch_async(dispatch_get_main_queue()) {
// update some UI
}
}
Swift 4.x
Mettez ceci dans un fichier:
func background(work: @escaping () -> ()) {
DispatchQueue.global(qos: .userInitiated).async {
work()
}
}
func main(work: @escaping () -> ()) {
DispatchQueue.main.async {
work()
}
}
puis appelez-le où vous avez besoin:
background {
//background job
main {
//update UI (or what you need to do in main thread)
}
}
Quoi qu'il en soit, je souhaite partager ma solution orientée objet à jour pour Swift 5 .
s'il vous plaît vérifier: AsyncTask
Inspiré conceptuellement par AsyncTask d'Android, j'ai écrit ma propre classe dans Swift
AsyncTask permet d'utiliser correctement et facilement le fil de l'interface utilisateur. Cette classe permet d'effectuer des opérations en arrière-plan et de publier les résultats sur le thread d'interface utilisateur.
Voici quelques exemples d'utilisation
Exemple 1 -
AsyncTask(backgroundTask: {(p:String)->Void in//set BGParam to String and BGResult to Void
print(p);//print the value in background thread
}).execute("Hello async");//execute with value 'Hello async'
Exemple 2 -
let task2=AsyncTask(beforeTask: {
print("pre execution");//print 'pre execution' before backgroundTask
},backgroundTask:{(p:Int)->String in//set BGParam to Int & BGResult to String
if p>0{//check if execution value is bigger than zero
return "positive"//pass String "poitive" to afterTask
}
return "negative";//otherwise pass String "negative"
}, afterTask: {(p:String) in
print(p);//print background task result
});
task2.execute(1);//execute with value 1
Il a 2 types génériques:
BGParam
- le type du paramètre envoyé à la tâche lors de son exécution.BGResult
- le type du résultat du calcul en arrière-plan.
Lorsque vous créez une AsyncTask, vous pouvez affecter ces types à tout ce dont vous avez besoin pour entrer et sortir de la tâche en arrière-plan, mais si vous n'avez pas besoin de ces types, vous pouvez le marquer comme inutilisé en le définissant simplement comme suit: Void
ou avec une syntaxe plus courte: ()
Lorsqu'une tâche asynchrone est exécutée, elle passe par 3 étapes:
beforeTask:()->Void
invoqué sur le thread d'interface utilisateur juste avant l'exécution de la tâche.backgroundTask: (param:BGParam)->BGResult
invoqué sur le thread d'arrière-plan immédiatement aprèsafterTask:(param:BGResult)->Void
invoqué sur le thread d'interface utilisateur avec le résultat de la tâche en arrière-planÉtant donné que la question relative à l'OP a déjà été répondue ci-dessus, je souhaite simplement ajouter quelques considérations de rapidité:
Je ne recommande pas d'exécuter des tâches avec la priorité de fil . Background, en particulier sur l'iPhone X où la tâche semble être allouée sur les cœurs à faible consommation.
Voici quelques données réelles d'une fonction de calcul intensif qui lit un fichier XML (avec mise en mémoire tampon) et effectue une interpolation de données:
Nom du périphérique/. Fond/.util/. Défaut/. UserInitiated/. UserInteractive
Notez que le jeu de données n’est pas le même pour tous les appareils. C'est le plus grand sur l'iPhone X et le plus petit sur l'iPhone 5.
Grand Central Dispatch est utilisé pour gérer le multitâche dans nos applications iOS.
Vous pouvez utiliser ce code
// Using time interval
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+1) {
print("Hello World")
}
// Background thread
queue.sync {
for i in 0..<10 {
print("Hello", i)
}
}
// Main thread
for i in 20..<30 {
print("Hello", i)
}
Plus d'informations utilisez ce lien: https://www.programminghub.us/2018/07/integrate-dispatcher-in-Swift.html
Fonction polyvalente pour fil
public enum QueueType {
case Main
case Background
case LowPriority
case HighPriority
var queue: DispatchQueue {
switch self {
case .Main:
return DispatchQueue.main
case .Background:
return DispatchQueue(label: "com.app.queue",
qos: .background,
target: nil)
case .LowPriority:
return DispatchQueue.global(qos: .userInitiated)
case .HighPriority:
return DispatchQueue.global(qos: .userInitiated)
}
}
}
func performOn(_ queueType: QueueType, closure: @escaping () -> Void) {
queueType.queue.async(execute: closure)
}
Utilisez-le comme:
performOn(.Background) {
//Code
}
J'aime beaucoup la réponse de Dan Beaulieu, mais elle ne fonctionne pas avec Swift 2.2 et je pense que nous pouvons éviter ces vilains déroulements forcés!
func backgroundThread(delay: Double = 0.0, background: (() -> Void)? = nil, completion: (() -> Void)? = nil) {
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
background?()
if let completion = completion{
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue()) {
completion()
}
}
}
}
dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0), {
// Conversion into base64 string
self.uploadImageString = uploadPhotoDataJPEG.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.EncodingEndLineWithCarriageReturn)
})