Nous avons le code pour télécharger la citation, mais toute nouvelle citation doit être accompagnée d'une nouvelle photo. Dans ce chapitre, nous allons télécharger les images !
Découvrez l'API d'Unsplash
Nous allons récupérer nos photos sur Unsplash. Unsplash est un site de partage de photos libres de droits. Elles sont souvent très esthétiques et je vous recommande le site pour vos applications, présentations, etc.
Unsplash propose une API que je vous invite à explorer à cette adresse : https://source.unsplash.com. Son API est un peu plus complète que Forismatic, mais une seule fonctionnalité nous intéresse : la récupération aléatoire de photos. Pour cela, il suffit de faire une requête GET à cette adresse :
https://source.unsplash.com/random
On peut même préciser la taille en pixels que l'on souhaite obtenir, en l'indiquant comme ceci :
https://source.unsplash.com/random/1000x1000
Je vous invite à tester cette API dans Postman. Vous devriez voir l'image dans le body en bas :
Je vous laisse jouer un peu avec, et quand vous maîtrisez cette partie de l'API Unsplash, passez à la suite !
Créez la tâche
Comme au chapitre précédent, nous allons commencer par créer notre URL :
private static let pictureUrl = URL(string: "https://source.unsplash.com/random/1000x1000")!
Ensuite, nous allons lancer notre appel dans une fonction getImage
:
private static func getImage() {
}
Dans cette fonction, on commence par créer notre URLSession
avec une configuration par défaut :
let session = URLSession(configuration: .default)
Et ensuite on crée notre tâche avec la méthode dataTask de URLSession :
let task = session.dataTask(with: pictureUrl) { (data, response, error) in
}
Mais on n’a pas créé de requête avec URLRequest !
Wow ! Quelle perspicacité ! Et moi qui pensais que ça allait passer inaperçu...
Eh oui ! Ici nous faisons une simple requête GET sans paramètre. Dans ce cas, on peut simplement passer une URL directement à la fonction dataTask . Par défaut, la tâche sera une requête GET sur l'URL indiquée. C'est plus rapide !
Ensuite, on n'oublie pas de lancer l'appel avec :
task.resume()
Gérez la réponse
Comme au chapitre précédent, on va gérer la réponse en vérifiant que la réponse n'a pas d'erreur, contient des données et a bien pour status code
200 :
let task = session.dataTask(with: pictureUrl) { (data, response, error) inguard let data = data, error == nil else {
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
return
}
}
}
Jusque-là, rien de nouveau !
La difficulté apparaît maintenant. En effet, on souhaite modifier la photo et la citation en même temps sur l'interface. Donc pour que cela fonctionne, on va chaîner les appels.
Il faut donc qu'on appelle la fonction getImage
une fois qu'on a reçu la citation :
let task = session.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
return
}
guard let response = response as? HTTPURLResponse, response.statusCode == 200 else {
return
}
guard let responseJSON = try? JSONDecoder().decode([String: String].self, from: data), let text = responseJSON["quoteText"],
let author = responseJSON["quoteAuthor"] else {
// gérer l’erreur de décodage
return
}
getImage() // Une fois la citation reçue, on va chercher l'image
}
Maintenant, comme on veut tout envoyer en même temps au contrôleur, il va nous falloir rassembler les données de la citation et de l'image au même endroit, et pour cela nous allons créer une fermeture.
Ajoutez une fermeture pour l'image
Nous allons ajouter une fermeture en paramètre de la fonction getImage
, on va appeler cela completionHandler
, et elle sera appelée dès qu'on a récupéré les données de l'image. Modifiez votre fonction getImage
comme ceci :
private static func getImage(completionHandler: @escaping ((Data?) -> Void)) {
let session = URLSession(configuration: .default)
let task = session.dataTask(with: pictureUrl) { (data, response, error) in
guard let data = data, error == nil else {
return
}
guard let response = response as? HTTPURLResponse,
response.statusCode == 200 else {
return
}
completionHandler(data) // On passe les données via le completionHandler
}
task.resume()
}
Alors que se passe-t-il ici ?
Ligne 1 : On rajoute le paramètre
completionHandler
de type((Data?) -> Void)
, soit une fonction qui prend en paramètre une valeur de typeData?
et qui ne renvoie rien.
Ligne 6 : Si la requête s'est bien passée, on passe les données reçues data dans le
completionHandler
.
Maintenant, il ne nous reste plus qu'à utiliser ça lorsqu'on appelle la fonction getImage
lors de la réception de la citation :
getImage { (data) in
guard let data = data {
return)
}
print(data)
}
Désormais, les données de l'image, de la citation et de l'auteur sont réunies au même endroit !
guard let responseJSON = try? JSONDecoder().decode([String: String].self, from: data), let text = responseJSON["quoteText"],
let author = responseJSON["quoteAuthor"] else {
return
}
getImage { (data) in
guard let dataImage = data else {
return
}
print(dataImage)
print(text)
print(author)
}
On va pouvoir utiliser ces trois données ensemble au prochain chapitre !
En résumé
Vous pouvez utiliser l’API libre de droits Unsplash pour télécharger des images avec Postman.
Pour récupérer des données de type image sans paramètre, vous devez créer une requête HTTP GET.
Pour configurer une requête GET :
lancez la tâche en utilisant la classe
URLSessionDataTask
directement avec l’URL. Inutile de configurer la requête si vous n’avez pas de paramètre ;n’oubliez pas de faire un
task.resume()
en lançant la tâche, sinon la requête ne partira jamais !
Pour lancer la requête POST puis la requête GET, vous avez appelé la méthode
getImage
depuisgetQuote
, une fois la citation obtenue dansgetQuote
.Pour transmettre les données de l’image à
getQuote,
uniquement lorsque celles-ci ont été récupérées par la requête, vous avez utilisé une fermeture nomméecompletionHandler
dansgetImage
.
Vous savez maintenant télécharger des images en réalisant des requêtes GET. Dans le prochain chapitre, nous allons utiliser nos données pour faire fonctionner notre contrôleur !