Erste Schritte mit AWS

Erstellen einer iOS-Anwendung

Erstellen Sie eine einfache iOS-Anwendung mit AWS Amplify

Modul 4: Hinzufügen einer GraphQL-API und einer Datenbank

In diesem Modul verwenden Sie die Amplify-CLI und -Bibliotheken zur Konfiguration und zum Hinzufügen einer GraphQL-API zu Ihrer Anwendung.

Einführung

Nachdem wir die Anwendung mit Benutzerauthentifizierung erstellt und konfiguriert haben, fügen wir nun eine API und CRUD-Operationen (Create, Read, Update, Delete) auf einer Datenbank hinzu.

In diesem Modul fügen Sie Ihrer Amplify-Anwendung unter Verwendung der Amplify-CLI und -Bibliotheken eine API hinzu. Die API, die Sie erstellen werden, ist eine GraphQL-API, die AWS AppSync (einen verwalteten GraphQL-Service) nutzt, der von Amazon DynamoDB (einer NoSQL-Datenbank) unterstützt wird. Eine Einführung in GraphQL finden Sie auf dieser Seite.

Die App, die Sie bauen werden, ist eine Notizbuch-App, mit der Benutzer Notizen erstellen, löschen und auflisten können. Dieses Beispiel gibt Ihnen eine gute Idee, wie Sie viele beliebte Arten von CRUD+L-Anwendungen (Erstellen, Lesen, Aktualisieren, Löschen und Auflisten) erstellen können.

Lerninhalte

  • Erstellen und Bereitstellen einer GraphQL-API
  • Schreiben von Front-End-Code zur Interaktion mit der API

Wichtige Konzepte

API – Stellt eine Programmierschnittstelle zur Verfügung, die Kommunikation und Interaktionen zwischen mehreren Software-Vermittlern ermöglicht.

GraphQL – Eine Abfragesprache und serverseitige API-Implementierung auf der Grundlage einer typisierten Darstellung Ihrer Anwendung. Diese API-Darstellung wird unter Verwendung eines Schemas deklariert, das auf dem GraphQL-Typsystem basiert. (Weitere Informationen über GraphQL finden Sie auf dieser Seite.)

 Veranschlagte Zeit

20 Minuten

 Verwendete Services

Implementierung

  • Erstellen eines GraphQL-API-Service und einer dazugehörigen Datenbank

    Um die GraphQL-API und die dazugehörige Datenbank zu erstellen, öffnen Sie ein Terminal und führen Sie diesen Befehl von Ihrem Projektverzeichnis aus:

    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

    Der Standardtexteditor, den Sie bei der Initialisierung des Projekts (amplify init) wählen, wird mit einem vordefinierten Datenschema geöffnet.

    Löschen Sie das Schema und ersetzen Sie es durch unser Anwendungs-GraphQL-Schema:

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

    Das Datenmodell besteht aus einer Klasse NoteData und 4 Eigenschaften: ID und Name sind obligatorisch. Beschreibung und Bild sind optionale Zeichenfolgen.

    Der @Modell-Transformator zeigt an, dass wir eine Datenbank zur Speicherung dieser Daten erstellen möchten.

    Der @auth-Transformator fügt Authentifizierungsregeln hinzu, um den Zugriff auf diese Daten zu ermöglichen. Für dieses Projekt möchten wir, dass nur der Eigentümer von NoteData Zugang zu diesen Daten hat.

    Wenn Sie fertig sind, vergessen Sie nicht zu speichern.

  • Clientseitigen Code erzeugen

    Basierend auf der soeben von uns erstellten GraphQL-Datenmodelldefinition generiert Amplify clientseitigen Code (d. h. Swift-Code) zur Darstellung der Daten in unserer Anwendung.

    Um den Code zu generieren, führen Sie in Ihrem Terminal den folgenden Befehl aus:

    amplify codegen models

    Dies erzeugt Swift-Dateien im Verzeichnis amplify/generated/models, wie Sie mit sehen können:

    ➜  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

    Importieren Sie diese Dateien in Ihr Xcode-Projekt: Suchen Sie sie im Finder und ziehen Sie sie per Drag & Drop in das Projekt in Xcode.

    iOSTutorial-Module4-Step1
  • Bereitstellung von API-Service und -Datenbank

    Um die Backend-API und die Datenbank, die wir gerade erstellt haben, bereitzustellen, gehen Sie zu Ihrem Terminal und führen Sie den Befehl aus:

    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

    Nach einigen Minuten sollten Sie eine Erfolgsmeldung sehen:

    ✔ All resources are updated in the cloud
    
    GraphQL endpoint: https://yourid.appsync-api.eu-central-1.amazonaws.com/graphql
  • API-Client-Bibliothek zum Xcode-Projekt hinzufügen

    Bevor wir zum Code übergehen, fügen Sie die Amplify-API-Bibliothek zu den Abhängigkeiten Ihres Projekts hinzu. Öffnen Sie die Podfile-Datei und fügen Sie die Zeile mit AmplifyPlugins/AWSAPIPlugin hinzu oder kopieren Sie die enire-Datei unten durch Kopieren/Einfügen.

    # 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

    Führen Sie den Befehl in einem Terminal aus:

    pod install

    Die Ausführung des Befehls dauert einige Augenblicke. Sie sollten dies sehen (die tatsächlichen Versionsnummern können variieren):

    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.
  • Amplify Libs zur Laufzeit initialisieren

    Zurück zu Xcode, öffnen Sie Backend.swift und fügen Sie eine Zeile in die Amplify Backend-Initialisierungssequenz in der Methode private init() hinzu. Der vollständige Codeblock sollte wie folgt aussehen:

    // 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)")
    }
  • Bridging zwischen GraphQL-Datenmodell und App-Modell hinzufügen

    Unser Projekt verfügt bereits über ein Datenmodell zur Darstellung einer Note. Also habe ich eine Design-Entscheidung getroffen, dieses Modell weiterhin zu verwenden und eine einfache Möglichkeit zur Konvertierung von NoteData in eine Note vorzusehen. Öffnen Sie ContentView.swift und fügen Sie diesen Initialisierer in die Notizklasse hinzu.

    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!
    }
  • Hinzufügen von API CRUD-Methoden zur Backend-Klasse

    Fügen wir 3 Methoden zum Aufruf unserer API hinzu: eine Methode zum Abfragen der Notiz, eine Methode zum Erstellen einer neuen Notiz und eine Methode zum Löschen einer Notiz. Beachten Sie, dass diese Methode auf dem App-Datenmodell arbeitet (Hinweis), um eine einfache Interraktion von der Benutzeroberfläche aus zu ermöglichen. Diese Methode konvertiert Note transparent in die NoteData-Objekte von GraphQL.

    Öffnen Sie die Datei Backend.swift und fügen Sie den folgenden Snipet am Ende der Backend-Klasse hinzu:

        // 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)")
                }
            }
        }

    Aktualisieren Sie in derselben Datei Backend.swift die Methode updateUserData(withSignInStatus:) so, dass sie wie folgt aussieht:

    // 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 = []
            }
        }
    }

    Jetzt muss nur noch ein Stück der Benutzeroberfläche erstellt werden, um eine neue Notiz zu erstellen und eine Notiz aus der Liste zu löschen.

  • Hinzufügen einer Bearbeitungsschaltfläche zum Hinzufügen einer Notiz

    Nachdem das Backend und die Datenmodellteile nun vorhanden sind, besteht der letzte Schritt in diesem Abschnitt darin, den Benutzern die Möglichkeit zu geben, eine neue Notiz zu erstellen und diese zu löschen.

    Öffnen Sie in Xcode ContentView.swift

    a. Fügen Sie in der ContentView-Struktur Zustandsvariablen hinzu, die an die Benutzeroberfläche gebunden sind.

    // 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. Fügen Sie an beliebiger Stelle in der Datei eine Ansichtsstruktur hinzu, damit der Benutzer eine neue Notiz erstellen kann:

    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. Fügen Sie eine +-Schaltfläche in der Navigationsleiste hinzu, um ein Blatt zur Erstellung einer Notiz zu präsentieren

    Zurück zur ContentView-Struktur, ersetzen Sie navigationBarItems(führende SignOutButton()) durch

        .navigationBarItems(leading: SignOutButton(),
                            trailing: Button(action: {
            self.showCreateNote.toggle()
        }) {
            Image(systemName: "plus")
        })
    }.sheet(isPresented: $showCreateNote) {
        AddNoteView(isPresented: self.$showCreateNote, userData: self.userData)
  • Hinzufügen eines Streichen-zum-Löschen-Verhaltens

    Fügen Sie schließlich in ContentView das Verhalten "Durchstreichen zum Löschen" hinzu: Fügen Sie die Methode .onDelete { } zur ForEach-Struktur hinzu:

    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)
        }
    }
  • Erstellen und testen

    Um zu überprüfen, ob alles wie erwartet funktioniert, bauen und betreiben Sie das Projekt. Klicken Sie auf das Menü Produkt und wählen Sie Ausführen oder geben Sie ⌘R ein. Es sollte kein Fehler vorliegen.

    Vorausgesetzt, Sie sind noch angemeldet, startet die App auf der Mitarbeiterliste. Sie hat jetzt eine +-Schaltfläche, um eine Notiz hinzuzufügen. Tippen Sie auf das +-Zeichen, tippen Sie auf Diese Notiz erstellen und die Notiz sollte in der Liste erscheinen.

    Sie können die AddNoteView schließen, indem Sie sie nach unten ziehen. Beachten Sie, dass es im iOS-Simulator nicht möglich ist, ein zweites Mal auf + zu tippen, Sie müssen zuerst die Liste 'ziehen, um sie neu zu laden'.

    Sie können Notiz löschen, indem Sie eine Zeile nach links streichen.

    Hier ist der vollständige Ablauf.

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

Fazit

Sie haben jetzt eine iOS-Anwendung erstellt! Mit AWS Amplify haben Sie eine GraphQL-API hinzugefügt und die Erstellungs-, Lese- und Löschfunktionen in Ihrer Anwendung konfiguriert.

Im nächsten Modul werden wir die Benutzeroberfläche und das Verhalten zur Verwaltung von Bildern hinzufügen.

War das Modul hilfreich?

Vielen Dank
Bitte teilen Sie uns mit, was Ihnen gefallen hat.
Schließen
Es tut uns Leid Sie zu enttäuschen
Ist etwas veraltet, verwirrend oder ungenau? Bitte helfen Sie uns, dieses Tutorial zu verbessern, indem Sie Feedback geben.
Schließen

Speicher hinzufügen