NSURLSession ordonnée
Bonjour à tous
Je suis un (presque) débutant en programmation iOS.
Pour m'entraà®ner et apprendre, je développe des micro-apps.
Et là je bute sur problème.
Je voudrais, sans librairie externe, avec NSURLSession, animer un UIImageView à partir de 10 images téléchargées sur un site internet.
Je me sers de NSURLSession sans trop de souci mais pas pour ce cas-là .
Le code est simple mais malheureusement NSURLSession ne télécharge pas les images dans l'ordre du coup l'animation ne fonctionne pas.
En bidouillant avec des semaphores et autres NSTimer j'y arrive mais je sais que ce n'est pas propre.
Pourriez-vous m'aider à avancer sur le sujet ?
Merci
Voici le code en question :
func imgTest() {
for urlPath in urlPaths {
let url:NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let request = NSMutableURLRequest(URL: url)
let task = session.dataTaskWithRequest(request) {
(let data, let response, let error) in
guard let _:NSData = data, let _:NSURLResponse = response where error == nil else { print("error")
return
}
dispatch_async(dispatch_get_main_queue(), {
let dataImg = UIImage(data: data!)
self.imagesListArray.append(dataImg!)
self.img_Radar.animationImages = self.imagesListArray
self.img_Radar.animationDuration = 3.0
self.img_Radar.animationRepeatCount = 10
self.img_Radar.startAnimating()
})
}
task.resume()
}
}
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Pourquoi est-ce que tu n'attends pas d'avoir récupéré les images en mémoire, avant de lancer l'animation ?
Tu peux aussi utiliser le balises de code du forum (symbole <> à coté de la bulle de bande dessinée) pour afficher le source d'une manière plus lisible.
Oui je n'aurais pas dû laisser le code pour l'animation.
Mais dans tous les cas que j'ai essayé le tableau n'est pas dans l'ordre.
Et les images au format binaire ne sont plus triables (enfin je pense)
Et c'est ça qui m'échappe...
Il faut que tu télécharges toutes les images. Les images ne sont effectivement pas triables, mais étant donné que c'est toi qui a lancé les requêtes, tu sais à quelle requête correspond chaque réponse et tu peux donc retrouver l'ordre: l'index de l'image est le même que celui de la requête.
C'est faisable, mais pas si simple, surtout quand on débute.
Le mieux est sans doute, quand tu reçois une image (donc dans ton bloc de completion de ta dataTaskWithRequest), de la réassocier à l'URL d'origine (dans un Dictionary par exemple, qui aurait pour clé l'URL et comme valeur l'image). Et une fois que toutes les images sont téléchargées, et donc que ton dictionnaire URL -> Image est rempli, tu tries les images en utilisant les URLs pour déterminer l'ordre.
Ca donnerait un truc comme ça :
L'idée est :
1) De ne mettre à jour ton tableau imagesListArray et commencer l'animation que quand toutes les requêtes de tes images sont toutes finies (quel que soit l'ordre dans lequel elles sont arrivées)
2) De construire le tableau d'images self.imagesListArray à partir de urlPaths (qui est dans un tableau déjà l'ordre que tu veux avoir) et de images (qui est un tableau faisant correspondre chaque urlPath à l'image associée une fois qu'elle est arrivée), en utilisant flatMap pour convertir ton tableau de String en tableau de UIImage
Le 2ème flatMap est nécessaire parce que les valeurs du dictionnaire "images" étant de type "UIImage?", alors "images[key]" retourne un "UIImage??" donc "flatMap { images[$0] }" va enlever un niveau d'Optional, mais il faut en enlever un 2ème avec un "flatMap { $0 }" pour avoir un tableau de "UIImage" et non de "UIImage?"
Une autre possibilité que le Dictionnaire consisterait à créer une petite classe pour lier l'url et l'image téléchargée.
Donc, plutôt que d'avoir un tableau d'url d'un côté et un tableau d'image de l'autre, tu aurais un tableau de RemoteImage.
Tu peux mettre ton appel à NSURLSession dans une fonction et capturer l'objet RemoteImage en cours dans la closure de completion de dataTaskWithRequest:
Tu peux utiliser un dispatch group pour exécuter un block quand toutes les images sont prêtes:
C'est écrit sans compilation, donc il y a surement des erreurs, mais l'idée est là .
Quand je pense que je croyais que c'était un exercice simple...!
::)
Merci à tous pour vos réponses très détaillées et pour le code que je vais m'empresser de décortiquer/tester dès ce soir.
Le flatMap, ça ne me dit rien, juste le .map dans le livre Swift d'Apple.
Quand au dispatch_group, là aussi il faut que je me rencarde.