Bon, tout est prêt pour enfin faire notre appel réseau.
Les Views SwiftUI sont immutable, c’est à dire qu’elles ne peuvent pas changer d’état. C’est pour cela que nous avons besoin de @State pour pouvoir modifier l’état de notre View.
Ici nous avons besoin de modifier l’état de notre View lorsque nous faisons un appel réseau. En effet, nous avons besoin de modifier l’état de notre View que lorsque nous recevons les données de l’API.
Comment réaliser cela, puisque notre vue est immutable et ne vit pas dans le même contexte que notre appel réseau ?
Nous allons utilisez les
tasketawaitpour réaliser cela. Ce sont l’équivalent desuseEffecten React / Native.
A ne jamais stocker en dur dans le code, ni commit sur Github.
Je vous fourni ici un fichier à mettre dans votre projet, qui permet de stocker des variables d’environnement.
environment.plist avec Xcodeclient_id avec votre clé d’API en valeur.
Puis dans votre code, à l’endroit où vous avez besoin de votre clé d’API, utilisez le code suivant :
ConfigurationManager.instance.plistDictionnary.clientId
environment.plist au .gitignore pour éviter de le commit sur Github.Pour des raisons de limite d’utilisation, créez un bouton sur votre interface LoadData qui permettra de lancer l’appel réseau, en lançant l’appel autrement votre preview SwiftUI risque de lancer trop souvent l’appel réseau et de vous bloquer l’accès à l’API.
D’ailleurs pensez à désactivez les AsyncImage que nous avons fait dans l’exercice précédent pour ne pas faire trop d’appel réseau.
Utilisez le code suivant pour faire un appel réseau à l’API Unsplash et récupérer une liste d’images.
struct ContentView: View {
// Déclaration d'une variable d'état, une fois remplie, elle va modifier la vue
@State var imageList: [UnsplashPhoto] = []
// Déclaration d'une fonction asynchrone
func loadData() async {
// Créez une URL avec la clé d'API
let url = URL(string: "https://api.unsplash.com/photos?client_id=\(ConfigurationManager.instance.plistDictionnary.clientId)")!
do {
// Créez une requête avec cette URL
let request = URLRequest(url: url)
// Faites l'appel réseau
let (data, response) = try await URLSession.shared.data(for: request)
// Transformez les données en JSON
let deserializedData = try JSONDecoder().decode([UnsplashPhoto].self, from: data)
// Mettez à jour l'état de la vue
imageList = deserializedData
} catch {
print("Error: \(error)")
}
}
// Créez cette nouvelle structure visuelle
var body: some View {
VStack {
// le bouton va lancer l'appel réseau
Button(action: {
Task {
await loadData()
}
}, label: {
Text("Load Data")
})
ScrollView {
... // Votre grille d'image
}
}
}
}
🛑 Si vous avez des erreurs de deserialisation dans la console, pensez à vérifier votre modèle
UnsplashPhoto:
- Utilisez les bon types
- Mettez les bonnes clés pour le décodage (
CodingKeys)- Mettez en optionnel les champs qui peuvent être
nulldans le JSON
Modifiez votre grille pour afficher les images que vous avez récupéré depuis l’API. En utilisant ForEach et AsyncImage avec la SOT (source of truth) imageList que vous avez créé dans l’exercice précédent.
La grille doit maintenant fonctionner avec l’appel réseau. Et donc des images différentes.
Il existe 3 façons de faire un appel asynchrone en Swift
async/awaitCombinecompletionHandler / GCDExpliquez les différences entre ces 3 méthodes.
Et voilà, la base de notre app est fonctionnelle !
async/await et taskForEach et AsyncImage pour afficher des images depuis une URL