[résolu] UIImage à  partir d'un lien Swift

redwinnerredwinner Membre
février 2016 modifié dans Objective-C, Swift, C, C++ #1

Bonjour tout le monde,


j'utilise 3 fonctions pour retourner un objet.

la première fonction va chercher dans un lien donné en paramètre pour retrouver plusieurs paramètres dont un String (qui est le lien d'une autre page) et sur ce lien retourné j'utilise une autre fonction pour obtenir le lien d'une image. La 3ème fonction agit sur le lien de l'image pour récupérer l'image.

c'est cette dernière fonction qui pose problème, la voiçi :

 



func getLinkImage(lien_news: String, separateur: String) -> String {
let url = NSURL(string: lien_news)
var link_image_news = "[url="http://www.siteweb.com"]http://www.siteweb.com"[/url]
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) -> Void in
if error == nil {
let urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding)
let urlContentArray = urlContent?.componentsSeparatedByString(separateur)
// recuperer lien Image
print(" Lien Image ")
var image_news = urlContentArray?[1].componentsSeparatedByString("<img alt=")
image_news = image_news?[1].componentsSeparatedByString("src=")
image_news = image_news?[1].componentsSeparatedByString("\"")
link_image_news = "[url="http://www.siteweb.com"]http://www.siteweb.com"[/url] + image_news![1]
print(link_image_news)
// fin recuperer lien Image
}
else {
print("Erreur lors du chargement du lien de l'image")
print(url!)
}
}
task.resume()
return link_image_news
}

lors de l'appel dans cette fonction dans "viewDidLoad()" ou viewDidLayoutSubviews(), j'ai d'abord l'affichage : http://www.siteweb.compuis après quelques secondes j'ai le lien de l'image qui est affiché.

c'est à  dire la valeur retournée est bien celle attribuée lors de l'initialization et non pas le lien de l'image obtenu.


merci d'avance pour votre aide.


Mots clés:

Réponses

  • CéroceCéroce Membre, Modérateur
    Je n'ai pas vraiment compris ton message, mais ça ressemble au problème classique: tu lances la requête dans viewDidLoad, or il faut du temps pour que le serveur web y réponde. Donc, quand tu fais l'affichage juste après l'appel de la méthode, forcément, le serveur n'a pas encore répondu, et c'est la valeur fixée à  l'init qui est affichée.
  • Joanna CarterJoanna Carter Membre, Modérateur
    S'il te plaà®t utiliser les balises code pour le séparer du texte. (Je l'ai fait cette fois)
  • redwinnerredwinner Membre
    février 2016 modifié #4

    Merci pour vos réponses, et désolé pour les balises codes :).


     


    ta remarque Céroce est pertinente mais je ne sais pas comment y remédier dans ce cas.


    J'ai utilisé le block dispatch_async mais c'est la même chose



    dispatch_async(dispatch_get_main_queue(), { () -> Void in

    })

  • CéroceCéroce Membre, Modérateur
    février 2016 modifié #5
    Quand on lance une requête réseau, on évite de faire ça sur le thread principal, parce qu'autrement il attend jusqu'à  ce que le serveur réponde (ou timeout). Comme le thread principal contrôle l'interface utilisateur, ça bloque l'appli!

    Donc, NSURLSession crée elle-même un deuxième thread pour faire la requête réseau. La question est: "comment est-on averti que le serveur a répondu?". Et la réponse, c'est que la méthode dataTaskWithURL prend un completionHandler en paramètre, une closure qui sera appelée lorsque c'est terminé " que ça ait réussi ou non.

    Il faudrait que ta méthode getLinkImage prenne elle-aussi une closure en paramètre pour avertir qu'il faut raffraà®chir le UILabel à  ce moment-là . Cette closure sera appelée par l'autre quand elle a fini.

    (les closures sont appelée "blocks" en Objective-C, en Swift, je crois bien qu'on dit "closures").
  • redwinnerredwinner Membre
    février 2016 modifié #6

    merci Céroce, j'ai compris le concept du thread principal, je pense que je dois revoir beaucoup de code écrit jusqu'à  maintenant :)


    j'ai cherché pour avoir quelques exemples mais je ne m'y trouve pas vu que je commence avec Swift.


     


    as-tu des exemples stp ?


  • CéroceCéroce Membre, Modérateur
    Non, mais cherche des exemples avec NSURLSession, même si c'est de l'Objective-C, le traduire en Swift n'est pas trop compliqué.
  • redwinnerredwinner Membre
    février 2016 modifié #8

    après plusieurs recherches, j'ai résolu le problème en changeant un peu le concept de la fonction.

    1 : j'ai enlevé le type de retour (qui était String) en Void (ne retourne rien)


    2 : j'ai utilisé deux fonctions, première pour avoir le Data concernant l'image et la deuxième pour attribuer le Data à  l'UIImage que je souhaite modifier



    func getDataFromUrl(url:NSURL, completion: ((data: NSData?, response: NSURLResponse?, error: NSError? ) -> Void)) {
    NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
    completion(data: data, response: response, error: error)
    }.resume()
    }

    func downloadImage(url: NSURL){
    print("Download Started")
    print("lastPathComponent: " + (url.lastPathComponent ?? ""))
    getDataFromUrl(url) { (data, response, error) in
    dispatch_async(dispatch_get_main_queue()) { () -> Void in
    guard let data = data where error == nil else { return }
    print(response?.suggestedFilename ?? "")
    print("Download Finished")
    self.image = UIImage(data: data)
    }
    }
    }

    3 : j'ai gardé ma fonction principale pour rechercher le lien de l'image


     


    NB : je me suis principalement servi de cette discussion : http://stackoverflow.com/questions/24231680/loading-image-from-url/27712427


     


    Merci à  tous pour votre aide


Connectez-vous ou Inscrivez-vous pour répondre.