Démarrer avec AWS

Créer une application iOS

Créer une application iOS simple avec AWS Amplify

Module 4 : ajouter une API GraphQL et une base de données

Dans ce module, vous allez utiliser la ligne d'interface de commande Amplify et des bibliothèques pour configurer et ajouter une API GraphQL à votre application.

Introduction

Maintenant que nous avons créé et configuré l'application avec un système d'authentification, nous allons ajouter une API ainsi que les opérations CRUD (créer, lire, modifier, supprimer) sur une base de données.

Dans ce module, vous allez ajouter une API à votre application en utilisant l'interface de ligne commande Amplify et des bibliothèques. L'API que vous allez créer est une API GraphQL qui exploite AWS AppSync (un service GraphQL géré) qui est soutenu par Amazon DynamoDB (une base de données NoSQL). Pour une introduction à GraphQL, consultez cette page.

Vous allez créer une application de prise de notes permettant aux utilisateurs de créer, supprimer et répertorier les notes. Cet exemple démontre clairement comment créer de nombreux types populaires d'applications CRUD+L (créer, lire, mettre à jour, supprimer et répertorier).

Ce que vous apprendrez

  • Créer et déployer une API GraphQL
  • Écrire du code front-end pour interagir avec l'API

Concepts clés

API : fournit une interface de programmation qui permet à plusieurs intermédiaires logiciels de communiquer et d'interagir.

GraphQL : une implémentation d'API côté serveur et de langage de requête basée sur une représentation typée de votre application. Cette représentation d'API est déclarée en utilisant un schéma basé sur le système de type GraphQL. (Pour en savoir plus sur GraphQL, consultez cette page.)

 Durée

20 minutes

 Services utilisés

Implémentation

  • Créer un service d'API GraphQL et une base de données

    Pour créer l'API GraphQL et sa base de données, ouvrez un terminal et exécutez cette commande depuis le répertoire de votre projet :

    amplify add api
    
    ? Please select from one of the below mentioned services: select GraphQL and press enter
    ? Provide API name: select the default, press enter
    ? Choose the default authorization type for the API: use the arrow key to select Amazon Cognito User Pool and press enter
    ? Do you want to configure advanced settings for the GraphQL API: select the default No, I am done and press enter
    ? Do you have an annotated GraphQL schema? keep the default N and press enter
    ? What best describes your project: choose any model, we are going to replace it with our own anyway. Press enter
    ? Do you want to edit the schema now? type Y and press enter

    L'éditeur de texte par défaut choisi à l'initialisation du projet (amplify init) s'ouvre avec un schéma de données pré-build.

    Supprimez ce schéma et remplacez-le par celui de notre application GraphQL :

    type NoteData
    @model
    @auth (rules: [ { allow: owner } ]) {
        id: ID!
        name: String!
        description: String
        image: String
    }

    Le modèle de données comprend une classe NodeData et quatre propriétés : « id » et « name » (nom) sont obligatoires, tandis que « description » et « image » sont des chaînes facultatives.

    Le transformateur @model indique que nous souhaitons créer une base de données pour stocker les données.

    Le transformateur @auth ajoute des règles d'authentification permettant l'accès à ces données. Pour ce projet, nous n'accorderons l'accès qu'au propriétaire de NodeData.

    Une fois que vous avez terminé, n'oubliez pas d'enregistrer.

  • Générer le code côté client

    Grâce à la définition du modèle de données GraphQL que nous venons de créer, Amplify génère le code côté client (c.-à-d. code Swift) pour représenter les données dans notre application.

    Pour générer le code, exécutez la commande suivante dans votre terminal :

    amplify codegen models

    Cette action crée des fichiers Swift dans le répertoire amplify/generated/models, comme vous pouvez le voir avec :

    ➜  iOS Getting Started git:(master) ✗ ls -al amplify/generated/models
    total 24
    drwxr-xr-x  5 stormacq  admin  160 Jul  9 14:20 .
    drwxr-xr-x  3 stormacq  admin   96 Jul  9 14:20 ..
    -rw-r--r--  1 stormacq  admin  380 Jul  9 14:20 AmplifyModels.swift
    -rw-r--r--  1 stormacq  admin  822 Jul  9 14:20 NoteData+Schema.swift
    -rw-r--r--  1 stormacq  admin  445 Jul  9 14:20 NoteData.swift

    Importez ces fichiers dans votre projet Xcode : localisez-les dans l'outil de recherche, puis glissez-déposez-les vers le projet dans Xcode.

    iOSTutorial-Module4-Step1
  • Déployer le service d'API et la base de données

    Pour déployer l'API backend et la base de données que nous venons de créer, ouvrez votre terminal et exécutez cette commande :

    amplify push
    # press Y when asked to continue
    
    ? Are you sure you want to continue? accept the default Y and press enter
    ? Do you want to generate code for your newly created GraphQL API type N and press enter

    Ce message de confirmation s'affiche après quelques minutes :

    ✔ All resources are updated in the cloud
    
    GraphQL endpoint: https://yourid.appsync-api.eu-central-1.amazonaws.com/graphql
  • Ajouter la bibliothèque Client API au projet Xcode

    Avant de passer au code, vous ajoutez la bibliothèque API Amplify aux dépendances de votre projet. Ouvrez le fichier Podfile et ajoutez la ligne avec AmplifyPlugins/AWSAPIPlugin ou copiez/collez le fichier entier ci-dessous.

    # you need at least version 13.0 for this tutorial, more recent versions are valid too
    platform :ios, '13.0'
    
    target 'getting started' do
      # Comment the next line if you don't want to use dynamic frameworks
      use_frameworks!
    
      # Pods for getting started
      pod 'Amplify', '~> 1.0'                             # required amplify dependency
      pod 'Amplify/Tools', '~> 1.0'                       # allows to call amplify CLI from within Xcode
    
      pod 'AmplifyPlugins/AWSCognitoAuthPlugin', '~> 1.0' # support for Cognito user authentication
      pod 'AmplifyPlugins/AWSAPIPlugin', '~> 1.0'         # support for GraphQL API
    
    end

    Dans un terminal, exécutez la commande :

    pod install

    L'exécution de la commande prend quelques instants. Le résultat suivant doit être produit (les numéros de version réels peuvent varier) :

    Analyzing dependencies
    Downloading dependencies
    Installing AmplifyPlugins 1.0.4
    Installing AppSyncRealTimeClient (1.1.6)
    Installing ReachabilitySwift (5.0.0)
    Installing Starscream (3.0.6)
    Generating Pods project
    Integrating client project
    Pod installation complete! There are 4 dependencies from the Podfile and 11 total pods installed.
  • Initialisation d'Amplify Libs à l'exécution

    De retour dans Xcode, ouvrez Backend.swift et ajoutez une ligne dans la séquence d'initialisation d'Amplify en suivant la méthode init() privée. Le bloc de code complet doit ressembler à ceci :

    // initialize amplify
    do {
       try Amplify.add(plugin: AWSCognitoAuthPlugin())
       try Amplify.add(plugin: AWSAPIPlugin(modelRegistration: AmplifyModels()))
       try Amplify.configure()
       print("Initialized Amplify")
    } catch {
       print("Could not initialize Amplify: \(error)")
    }
  • Ajout d'un pont entre le modèle de données GraphQL et le modèle d'application

    Notre projet dispose déjà d'un modèle de données pour représenter une note. J'ai donc pris la décision de conception de continuer à utiliser ce modèle et de fournir un moyen simple pour convertir un objet NoteData en note. Ouvrez ContentView.swift et ajoutez cet initialiseur à la classe Note.

    convenience init(from data: NoteData) {
        self.init(id: data.id, name: data.name, description: data.description, image: data.image)
     
        // store API object for easy retrieval later
        self._data = data
    }
    
    fileprivate var _data : NoteData?
    
    // access the privately stored NoteData or build one if we don't have one.
    var data : NoteData {
    
        if (_data == nil) {
            _data = NoteData(id: self.id,
                                name: self.name,
                                description: self.description,
                                image: self.imageName)
        }
    
        return _data!
    }
  • Ajout de méthodes CRUD d'API à la classe Backend

    Nous allons ajouter trois méthodes d'appel de notre API : interroger la Note, créer une Note et supprimer une Note. Ces méthodes fonctionnent sur le modèle de données de l'application (Note) pour simplifier l'interaction à partir de l'interface utilisateur. Elles permettent de convertir en toute transparence une note en objets NoteData GraphQL.

    Ouvrez le fichier Backend.swift et ajoutez cet extrait de code à la fin de la classe Backend :

        // MARK: API Access
    
        func queryNotes() {
    
            _ = Amplify.API.query(request: .list(NoteData.self)) { event in
                switch event {
                case .success(let result):
                    switch result {
                    case .success(let notesData):
                        print("Successfully retrieved list of Notes")
    
                        // convert an array of NoteData to an array of Note class instances
                        for n in notesData {
                            let note = Note.init(from: n)
                            DispatchQueue.main.async() {
                                UserData.shared.notes.append(note)
                            }
                        }
    
                    case .failure(let error):
                        print("Can not retrieve result : error  \(error.errorDescription)")
                    }
                case .failure(let error):
                    print("Can not retrieve Notes : error \(error)")
                }
            }
        }
    
        func createNote(note: Note) {
    
            // use note.data to access the NoteData instance
            _ = Amplify.API.mutate(request: .create(note.data)) { event in
                switch event {
                case .success(let result):
                    switch result {
                    case .success(let data):
                        print("Successfully created note: \(data)")
                    case .failure(let error):
                        print("Got failed result with \(error.errorDescription)")
                    }
                case .failure(let error):
                    print("Got failed event with error \(error)")
                }
            }
        }
    
        func deleteNote(note: Note) {
    
            // use note.data to access the NoteData instance
            _ = Amplify.API.mutate(request: .delete(note.data)) { event in
                switch event {
                case .success(let result):
                    switch result {
                    case .success(let data):
                        print("Successfully deleted note: \(data)")
                    case .failure(let error):
                        print("Got failed result with \(error.errorDescription)")
                    }
                case .failure(let error):
                    print("Got failed event with error \(error)")
                }
            }
        }

    Dans le même fichier Backend.swift, mettez à jour la méthode updateUserData(withSignInStatus:) comme suit :

    // change our internal state, this triggers an UI update on the main thread
    func updateUserData(withSignInStatus status : Bool) {
        DispatchQueue.main.async() {
            let userData : UserData = .shared
            userData.isSignedIn = status
    
            // when user is signed in, query the database, otherwise empty our model
            if status {
                self.queryNotes()
            } else {
                userData.notes = []
            }
        }
    }

    Maintenant, il ne nous reste plus qu'à créer un élément d'interface utilisateur permettant de créer et de supprimer une note de la liste.

  • Ajout d'un bouton Modifier pour ajouter une note

    Maintenant que le backend et le modèle de données sont en place, il ne nous reste plus qu'à permettre aux utilisateurs de créer et de supprimer une note.

    Dans Xcode, ouvrez ContentView.swift

    a. Dans la structure ContentView, ajoutez des variables d'état associées à l'interface utilisateur.

    // add at the begining of ContentView class
    @State var showCreateNote = false
    
    @State var name : String        = "New Note"
    @State var description : String = "This is a new note"
    @State var image : String       = "image"

    b. N'importe où dans le fichier, ajoutez une structure View pour permettre à l'utilisateur de créer une note :

    struct AddNoteView: View {
        @Binding var isPresented: Bool
        var userData: UserData
    
        @State var name : String        = "New Note"
        @State var description : String = "This is a new note"
        @State var image : String       = "image"
        var body: some View {
            Form {
    
                Section(header: Text("TEXT")) {
                    TextField("Name", text: $name)
                    TextField("Name", text: $description)
                }
    
                Section(header: Text("PICTURE")) {
                    TextField("Name", text: $image)
                }
    
                Section {
                    Button(action: {
                        self.isPresented = false
                        let noteData = NoteData(id : UUID().uuidString,
                                                name: self.$name.wrappedValue,
                                                description: self.$description.wrappedValue)
                        let note = Note(from: noteData)
    
                        // asynchronously store the note (and assume it will succeed)
                        Backend.shared.createNote(note: note)
    
                        // add the new note in our userdata, this will refresh UI
                        self.userData.notes.append(note)
                    }) {
                        Text("Create this note")
                    }
                }
            }
        }
    }

    c. Ajoutez un bouton + dans la barre de navigation pour fournir une feuille permettant de créer une note

    De retour dans la structure ContentView, remplacez navigationBarItems(leading SignOutButton()) par

        .navigationBarItems(leading: SignOutButton(),
                            trailing: Button(action: {
            self.showCreateNote.toggle()
        }) {
            Image(systemName: "plus")
        })
    }.sheet(isPresented: $showCreateNote) {
        AddNoteView(isPresented: self.$showCreateNote, userData: self.userData)
  • Ajout d'un comportement « balayer pour supprimer »

    Enfin, dans ContentView, ajoutez le comportement « balayer pour supprimer » : ajoutez la méthode .onDelete { } pour la structure ForEach :

    ForEach(userData.notes) { note in
        ListRow(note: note)
    }.onDelete { indices in
        indices.forEach {
            // removing from user data will refresh UI
            let note = self.userData.notes.remove(at: $0)
    
            // asynchronously remove from database
            Backend.shared.deleteNote(note: note)
        }
    }
  • Développement et test

    Pour vérifier que tout fonctionne comme prévu, générez et exécutez le projet. Cliquez sur le menu Produit et sélectionnez Exécuter ou tapez ⌘R. Il ne devrait y avoir aucune erreur.

    Si vous êtes toujours connecté, l'application démarre à partir d'une liste vide. Elle comporte désormais un bouton + permettant d'ajouter une note. Appuyez sur le signe +, appuyez sur Create this Note (Créer cette note) et la note doit apparaître dans la liste.

    Vous pouvez fermer AddNoteView en le tirant vers le bas. Notez que, dans le simulateur iOS, il n'est pas possible d'appuyer sur + une deuxième fois, vous devez « tirer pour actualiser » la liste d'abord.

    Vous pouvez désormais supprimer une note en balayant sa ligne vers la gauche.

    Voici la procédure complète.

    iOSTutorial-Module4-step2
    iOSTutorial-Module4-step3
    iOSTutorial-Module4-step4
    iOSTutorial-Module4-step5

Conclusion

Vous avez créé une application iOS ! En utilisant AWS Amplify, vous avez ajouté une API GraphQL et configuré des fonctionnalités de création, de lecture et de suppression dans votre application.

Dans le prochain module, nous ajouterons une interface utilisateur ainsi que des règles de gestion des images.

Ce module vous a-t-il été utile ?

Merci
Merci de nous indiquer ce que vous avez aimé.
Fermer
Nous sommes désolés de vous décevoir.
Quelque chose est-il obsolète, déroutant ou inexact ? Aidez-nous à améliorer ce didacticiel en fournissant des commentaires.
Fermer

Augmenter la capacité de stockage