1
votes

Fonction asynchrone iOS pas en ordre

Je suis nouveau dans les trucs asynchrones dans Swift, et j'essaie d'implémenter un simple appel asynchrone à une fonction.

A
start async
B
123.456

Quand je l'exécute, j'obtiens

A
start async
123.456
B

Comme la fonction est appelée de manière asynchrone, je me serais attendu à obtenir

import UIKit

func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
    print("start async")
    sleep(5)   // to simulate long work
    let result: Double = 123.456
    completionHandler(result)
}

print("A")

doAsyncStuff() { result in
    print(result)
}

print("B")

Où me suis-je trompé? Merci beaucoup


2 commentaires

Votre fonction n'a malheureusement rien à voir avec une exécution asynchrone


ce n'est pas un asynchrone


4 Réponses :


3
votes

Le problème est que vous appelez sleep , qui est une fonction de blocage synchrone, donc vous bloquez le thread principal pendant 5 secondes et rien d'autre ne peut être exécuté entre-temps. Vous devez utiliser DispatchQueue.asyncAfter pour tester des appels asynchrones simples.

Vous pouvez également savoir que votre fonction n'est pas asynchrone, car vous n'avez pas reçu d'erreur du compilateur pour ne pas marquer votre fermeture comme @escaping , ce que vous devez faire pour les gestionnaires d'achèvement asynchrone.

func doAsyncStuff(completionHandler: @escaping (_ result: Double) -> Void) {
    print("start async")
    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        completionHandler(123.456)
    }
}


0 commentaires

1
votes

Attention, vous appelez votre fonction sur le même thread, donc elle sera synchrone!

Pour l'appeler de manière asynchrone, créez un thread / tâche d'arrière-plan et appelez votre fonction à partir de ce thread d'arrière-plan. Une façon de le faire:

print("A")
DispatchQueue.global(qos: .background).async {
    //this is a background thread, do in it your async stuff
    doAsyncStuff() { result in
        print(result)
    }
}
print("B")


1 commentaires

Merci beaucoup, c'est plus clair maintenant pour moi, DispatchQueue manquait



1
votes

Utilisez DispatchQueue.main.asyncAfter pour un appel asynchrone dans swift. Votre code devrait donc ressembler à ..

func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
    print("start async")
    DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
    // your code goes from here
        let result: Double = 123.456
        completionHandler(result)
    }

}


0 commentaires

2
votes

Votre fonction n'est pas asynchrone. Chaque ligne de code est exécutée de manière synchrone (c'est-à-dire en attendant que la ligne se termine avant de s'exécuter). Ainsi, sleep (5) interrompt l'exécution au milieu de la fonction et print ("B") n'est appelé qu'après le retour de la fonction.

Vous pouvez utiliser Grand Central Dispatch (GCD) pour exécuter du code de manière asynchrone sur un thread différent. Voici un exemple:

import UIKit

func doAsyncStuff ( completionHandler: (_ result: Double) -> Void) {
    DispatchQueue.global(qos: .background).async { [weak self] in
        print("start async")
        sleep(5)
        let result: Double = 123.456
        completionHandler(result)
    }
}

print("A")

doAsyncStuff() { result in
    print(result) // This is your completion handler code
}

print("B")


0 commentaires