J’ai créé une fonction qui est censée me retourner le résultat d’une requête Alamofire, mais voila, du fait qu’il est asynchrone, il me renvois le résultat sans attendre la fin d’Alamofire. Je sais pas si je suis clair
private func requeteVote(url:String) -> String {
var result:String = "Wait for Alamofire"
Alamofire.request(url, encoding: JSONEncoding.default).responseJSON { (response) in
if let response = response.result.value,
let JSON = response as? NSDictionary {
print(JSON["result"]!) // ca va afficher ce que je veux, avec une petit latence, normal, c'est asynchrone
result = JSON["result"] as! String
}
}
print result //ca me permet de controller ce qui est retourné a quel moment
return result
}
le return de la fonction n’attend pas la valeur de retour d’Alamofire avant de me la renvoyer.
Je ne connais pas très bien AlamoFire mais, de ce que j’en comprends, tout comme un reloadData de tableView par exemple, je pense que ça pourrait se régler en faisant le return de manière asynchrone.
Par exemple (mais certainement à adapter dans ton cas) :
Je te conseil d’utiliser une closure pour renvoyer la valeur de retour.
Du coup sa nous donne :
private func requeteVote(url:String,completionHandler: (_ result:String) → Void ) {
var result:String = « Wait for Alamofire »
Alamofire.request(url, encoding: JSONEncoding.default).responseJSON { (response) in
if let response = response.result.value,
let JSON = response as? NSDictionary {
print(JSON[« result »]!) // ca va afficher ce que je veux, avec une petit latence, normal, c’est asynchrone
result = JSON[« result »] as! String
print result //ca me permet de controller ce qui est retourné a quel moment
completionHandler(result)
}
}
}
Quand tu va compiler xcode va te rajouter un @escaping devan le completionhandler (je ne sais pa pourquoi) mais ne tkt pas c’est normal.
Et tu l’utilise comme ceci :
var myResult = String()
requestVote(url:« Some URl »,completionHandler:{ (result) in
myResult = result
})
Il y a des chances que ce soit @Samir qui ait la bonne méthode puisque je n’ai jamais utilisé AlamoFire donc, en ce qui me concerne, c’était juste une piste
Samir, lui, a l’air d’avoir déjà pratiqué
Je ne sais pas si la notion de closure et claire pour toi mais je vais essayer d’expliquer du mieu que je peu.
Alor en fait l’idée est de passer en paramètre d’une fonction une “autre fonction”, et l’idée c’est d’appeler cette fonction une fois la tâche terminer.
Donc imaginons l’exemple suivant:
func faireTache(param1 :String , param2: (_ param)->Void ){
//Processing
let kkchose = autrekkchose
// ici on va appeler le param2 qui est une fonction et on va lui passer en paramètre notre "kkchose"
param2(kkchose)
}
func count(completion:(_terminer:Bool)->Void{
for x in 0...100000000000000000{
//On fai un calcul de malade
}
completion(true)
}
func test(){
print("debut de la fonction")
count({ (terminer) in
print("calcul terminer")
})
print("fonction terminer")
}
Si on observe la consol on devrai avoir
debut de la fonction
fonction termine
calcul terminer
Je trouve que ton exemple est bon Mon pseudo est @mbritto je ne reçoit pas les notifications avec @maxime.britto. Ça devait être un compte de tests que je dois supprimer
Les closures sont souvent complexes à comprendre mais ici le problème venait surtout de la notion asynchrone. @didier tu ne peux pas retourner le résultat d’un téléchargement avec le return d’une fonction, ni juste après avoir lancé le téléchargement car celui-ci est toujours en cours.
Une requête réseau est lente, très lente, très très lente à l’echelle de l’exécution de lignes de code. On choisit donc de les exécuter en asynchrone. Quand tu lances un téléchargement avec alamofire en fait tu ne fais que programmer une tâche future qui se fera dans quelques millisecondes (voire quelques secondes). Pour pouvoir traiter le résultat on transmet le code à exécuter lorsque le téléchargement sera terminé sous la forme de closure. Alamofire va sauvegarder cette closure pendant tout le temps du téléchargement et lorsque tout sera terminé il exécutera le code de cette closure en lui passant le résultat en paramètre.
Quand tu fais ceci
En fait tu programmes le téléchargement mais juste après l’avoir programmé tu essaies d’utiliser la variable myResult alors qu’elle est encore vide.
Elle sera remplie plus tard, bien après que cette fonction soit terminée, quand la closure sera exécutée
La correction de @Samir consiste à attendre que le chargement soit terminé et traité avant d’utiliser myResult en le plaçant dans la closure que tu envoies à alamofire.