#Appel Reseau

Bon, tout est prêt pour enfin faire notre appel réseau.

#Un peu de théorie

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 ?

Code Asynchrone

Nous allons utilisez les task et async / await pour réaliser cela. Une Task est une tâche asynchrone qui va permettre de réaliser des opérations asynchrones, et await va permettre d’attendre le résultat de cette tâche. await fonctionne de la même manière que await en Javascript, il va attendre que la tâche soit terminée pour continuer.

#La clé d’API

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.

  1. Une fois le fichier dans votre projet, créez un fichier environment.plist avec Xcode
  2. Ouvrez le fichier avec Xcode et ajoutez y une variable client_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 :

swift
ConfigurationManager.instance.plistDictionnary.clientId
  1. Enfin ajouter le fichier environment.plist au .gitignore pour éviter de le commit sur Github.

#🔧 Exercice 1 ~1h

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.

swift
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 null dans le JSON

#🔧 Exercice 2 ~20min

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.

#🔧 Exercice 3 ~20min

  • Il existe 3 façons de faire un appel asynchrone en Swift

    • async/await
    • Combine
    • completionHandler / GCD
  • Expliquez les différences entre ces 3 méthodes.


Et voilà, la base de notre app est fonctionnelle !

#En résumé

  • Nous avons vu comment faire un appel réseau avec async/await et task
  • Nous avons vu comment utiliser des variables d’environnement pour stocker des clés d’API
  • Nous avons deserialisé des données JSON en objet Swift
  • Nous avons utilisé ForEach et AsyncImage pour afficher des images depuis une URL