Erste Schritte mit AWS
Erstellen einer iOS-Anwendung
Erstellen Sie eine einfache iOS-Anwendung mit AWS Amplify
Modul 5: Hinzufügen der Funktion, Bilder zu speichern
In diesem Modul fügen Sie Speicherplatz hinzu und haben die Möglichkeit, ein Bild mit den Notizen in Ihrer App zu verknüpfen.
Einführung
Nun, da die Notizen-App funktioniert, wollen wir die Möglichkeit hinzufügen, jeder Notiz ein Bild zuzuordnen. In diesem Modul werden Sie die Amplify CLI und Bibliotheken verwenden, um einen Speicher-Service zu erstellen, der Amazon S3 nutzt. Schließlich werden Sie die iOS-Anwendung aktualisieren, um das Hochladen, Abrufen und Rendern von Bildern zu ermöglichen.
Lerninhalte
- Erstellen eines Speicher-Services
- Aktualisieren Ihrer IOS-App: die Logik zum Hoch- und Herunterladen von Bildern
- Aktualisieren Ihrer IOS-App: die Benutzeroberfläche
Wichtige Konzepte
Speicher-Service – Das Speichern und Abfragen von Dateien wie Bildern und Videos ist eine allgemeine Anforderung für die meisten Anwendungen. Eine Möglichkeit, dies zu tun, besteht darin, die Datei Base64 zu kodieren und als String zu senden, um sie in der Datenbank zu speichern. Dies bringt Nachteile mit sich, wie z. B. dass die kodierte Datei größer ist als die ursprüngliche Binärdatei, dass die Operation rechenintensiv ist und dass die Kodierung und Dekodierung komplizierter wird. Eine weitere Option ist ein speziell für die Dateiablage entwickelter und optimierter Service. Speicherdienste wie Amazon S3 existieren, um dies so einfach, performant und kostengünstig wie möglich zu machen.
Veranschlagte Zeit
10 Minuten
Verwendete Services
Implementierung
-
Erstellen Sie den Speicher-Service
Um Bildspeicherfunktionen hinzuzufügen, verwenden wir die Amplify-Speicherkategorie:
amplify add storage ? Please select from one of the below mentioned services: accept the default Content (Images, audio, video, etc.) and press enter ? Please provide a friendly name for your resource that will be used to label this category in the project: type image and press enter ? Please provide bucket name: accept the default and press enter ? Who should have access: accept the default Auth users only and press enter ? What kind of access do you want for Authenticated users? select all three options create/update, read, delete using the space and arrows keys, then press enter ? Do you want to add a Lambda Trigger for your S3 Bucket? accept the default No and press enter
Nach einer Weile sollten Sie Folgendes sehen:
Successfully added resource image locally
-
Bereitstellen des Speicher-Service
Um den soeben von uns bereitgestellten Speicher-Service bereitzustellen, gehen Sie zu Ihrem Terminal und führen Sie den Befehl aus:
amplify push
Drücken Sie Y zum Bestätigen und nach einer Weile sollten Sie Folgendes sehen:
✔ Successfully pulled backend environment amplify from the cloud.
-
Hinzufügen von Amplify-Speicher-Bibliotheken zum Xcode-Projekt
Bevor wir zum Code übergehen, fügen Sie die Amplify-Speicher-Bibliothek zu den Abhängigkeiten Ihres Projekts hinzu. Öffnen Sie die Podfile-Datei und fügen Sie die Zeile mit AmplifyPlugins/AWSS3StoragePlugin hinzu oder kopieren Sie die gesamte Datei
# 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 pod 'AmplifyPlugins/AWSS3StoragePlugin', '~> 1.0' # support for Amazon S3 storage 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 AWSS3 (2.14.2) Installing AmplifyPlugins 1.0.4 Generating Pods project Integrating client project Pod installation complete! There are 5 dependencies from the Podfile and 12 total pods installed.
-
Speicher-Plugin 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.add(plugin: AWSS3StoragePlugin()) try Amplify.configure() print("Initialized Amplify"); } catch { print("Could not initialize Amplify: \(error)") }
-
Hinzufügen von Image-CRUD-Methoden zur Backend-Klasse
Backend.swift öffnen. Fügen Sie an beliebiger Stelle in der Backend-Klasse die folgenden Methoden hinzu:
// MARK: - Image Storage func storeImage(name: String, image: Data) { // let options = StorageUploadDataRequest.Options(accessLevel: .private) let _ = Amplify.Storage.uploadData(key: name, data: image,// options: options, progressListener: { progress in // optionlly update a progress bar here }, resultListener: { event in switch event { case .success(let data): print("Image upload completed: \(data)") case .failure(let storageError): print("Image upload failed: \(storageError.errorDescription). \(storageError.recoverySuggestion)") } }) } func retrieveImage(name: String, completed: @escaping (Data) -> Void) { let _ = Amplify.Storage.downloadData(key: name, progressListener: { progress in // in case you want to monitor progress }, resultListener: { (event) in switch event { case let .success(data): print("Image \(name) loaded") completed(data) case let .failure(storageError): print("Can not download image: \(storageError.errorDescription). \(storageError.recoverySuggestion)") } } ) } func deleteImage(name: String) { let _ = Amplify.Storage.remove(key: name, resultListener: { (event) in switch event { case let .success(data): print("Image \(data) deleted") case let .failure(storageError): print("Can not delete image: \(storageError.errorDescription). \(storageError.recoverySuggestion)") } } ) }
-
Bild laden, wenn Daten von der API abgerufen werden
Nun, da wir unsere Backend-Funktionen zur Verfügung haben, laden wir die Bilder, wenn der API-Aufruf zurückkehrt. Die zentrale Stelle zum Hinzufügen dieses Verhaltens ist, wenn die Anwendung eine Hinweis-Benutzeroberfläche aus den von der API zurückgegebenen Hinweisdaten konstruiert.
Öffnen Sie ContentView.swift und aktualisieren Sie den Initialisierer der Notiz (fügen Sie die Zeilen 8 bis 17 hinzu):
// add a publishable's object property @Published var image : Image? // update init's code convenience init(from data: NoteData) { self.init(id: data.id, name: data.name, description: data.description, image: data.image) if let name = self.imageName { // asynchronously download the image Backend.shared.retrieveImage(name: name) { (data) in // update the UI on the main thread DispatchQueue.main.async() { let uim = UIImage(data: data) self.image = Image(uiImage: uim!) } } } // store API object for easy retrieval later self._data = data }
Wenn ein Bildname in der Instance von Note vorhanden ist, ruft der Code retrieveImage auf. Dies ist eine asynchrone Funktion. Es ist eine Funktion erforderlich, die beim Herunterladen des Bildes aufgerufen wird. Die Funktion erstellt ein Image-UI-Objekt und weist es der Instance von Note zu. Beachten Sie, dass diese Zuordnung eine Aktualisierung der Benutzeroberfläche auslöst und daher im Hauptthread der Anwendung mit DispatchQueue.main.async geschieht.
-
Hinzufügen von UI-Code zum Erfassen eines Bildes
Zunächst fügen wir generischen Code zur Unterstützung der Bilderfassung hinzu. Dieser Code kann in vielen Anwendungen wiederverwendet werden; er zeigt einen Bildauswahlschalter, mit dem der Benutzer ein Bild aus seiner Bildbibliothek auswählen kann.
Erstellen Sie in Xcode die neue Swift-Datei (⌘N, wählen Sie dann Swift). Benennen Sie die Datei CaptureImageView.swift und fügen Sie diesen Code hinzu:
import Foundation import UIKit import SwiftUI struct CaptureImageView { /// MARK: - Properties @Binding var isShown: Bool @Binding var image: UIImage? func makeCoordinator() -> Coordinator { return Coordinator(isShown: $isShown, image: $image) } } class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { @Binding var isCoordinatorShown: Bool @Binding var imageInCoordinator: UIImage? init(isShown: Binding<Bool>, image: Binding<UIImage?>) { _isCoordinatorShown = isShown _imageInCoordinator = image } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { guard let unwrapImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return } imageInCoordinator = unwrapImage isCoordinatorShown = false } func imagePickerControllerDidCancel(_ picker: UIImagePickerController) { isCoordinatorShown = false } } extension CaptureImageView: UIViewControllerRepresentable { func makeUIViewController(context: UIViewControllerRepresentableContext<CaptureImageView>) -> UIImagePickerController { let picker = UIImagePickerController() picker.delegate = context.coordinator // picker.sourceType = .camera // on real devices, you can capture image from the camera // see https://medium.com/better-programming/how-to-pick-an-image-from-camera-or-photo-library-in-swiftui-a596a0a2ece return picker } func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<CaptureImageView>) { } }
-
Bild speichern, wenn Notizen erstellt werden
Rufen wir die Speichermethoden aus dem Backend auf, wenn eine Notiz erstellt wird. Öffnen Sie ContentView.swift und ändern Sie die AddNoteView, um eine ImagePicker-Komponente hinzuzufügen:
// at the start of the Content View struct @State var image : UIImage? // replace the previous declaration of image @State var showCaptureImageView = false // in the view, replace the existing PICTURE section Section(header: Text("PICTURE")) { VStack { Button(action: { self.showCaptureImageView.toggle() }) { Text("Choose photo") }.sheet(isPresented: $showCaptureImageView) { CaptureImageView(isShown: self.$showCaptureImageView, image: self.$image) } if (image != nil ) { HStack { Spacer() Image(uiImage: image!) .resizable() .frame(width: 250, height: 200) .clipShape(Circle()) .overlay(Circle().stroke(Color.white, lineWidth: 4)) .shadow(radius: 10) Spacer() } } } }
Ändern Sie den Abschnitt Notiz erstellen, um sowohl das Bild als auch die Notiz zu speichern:
Section { Button(action: { self.isPresented = false let note = Note(id : UUID().uuidString, name: self.$name.wrappedValue, description: self.$description.wrappedValue) if let i = self.image { note.imageName = UUID().uuidString note.image = Image(uiImage: i) // asynchronously store the image (and assume it will work) Backend.shared.storeImage(name: note.imageName!, image: (i.pngData())!) } // 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 withAnimation { self.userData.notes.append(note) } }) { Text("Create this 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.
Angenommen, Sie sind noch angemeldet, startet die App auf der Liste mit einer Notiz. Verwenden Sie erneut das +-Zeichen, um eine Notiz zu erstellen. Fügen Sie diesmal ein aus dem lokalen Bildspeicher ausgewähltes Bild hinzu.
Hier ist der vollständige Ablauf.
Fazit
Sie haben mit AWS Amplify eine iOS-Anwendung erstellt! Sie haben Ihrer Anwendung eine Authentifizierung hinzugefügt, mit der Benutzer sich anmelden, einloggen und ihr Konto verwalten können. Die Anwendung verfügt außerdem über eine skalierbare GraphQL-API, die mit einer Amazon DynamoDB-Datenbank konfiguriert ist und es Benutzern ermöglicht, Notizen zu erstellen und zu löschen. Sie haben auch einen Dateispeicher mit Amazon S3 hinzugefügt, der es Benutzern ermöglicht, Bilder hochzuladen und in ihrer Anwendung anzusehen.
Im letzten Abschnitt finden Sie Anweisungen zur Wiederverwendung oder zum Löschen des soeben erstellten Backends.
-
Teilen Sie Ihr Backend zwischen mehreren Projekten
Amplify macht es einfach, ein einziges Backend für mehrere Frontend-Anwendungen gemeinsam zu nutzen.
Navigieren Sie in einem Terminal zu Ihrem anderen Projektverzeichnis und führen Sie den folgenden Befehl aus:
mkdir other-project cd other-project amplify pull ? Do you want to use an AWS profile? accept the default Yes and press enter ? Please choose the profile you want to use select the profile you want to use and press enter ? Which app are you working on? select the backend you want to share and press enter ? Choose your default editor: select you prefered text editor and press enter ? Choose the type of app that you're building select the operating system for your new project and press enter ? Do you plan on modifying this backend? most of the time, select No and press enter. All backend modifications can be done from the original iOS project.
Nach einigen Sekunden sehen Sie die folgende Meldung:
Added backend environment config object to your project. Run 'amplify pull' to sync upstream changes.
Sie können die beiden Konfigurationsdateien sehen, die herausgezogen wurden. Wenn Sie auf die Frage "Planen Sie eine Änderung dieses Backends?" mit "Ja" antworten, sehen Sie auch ein Amplify Backend.
➜ other-project git:(master) ✗ ls -al total 24 drwxr-xr-x 5 stormacq admin 160 Jul 10 10:28 . drwxr-xr-x 19 stormacq admin 608 Jul 10 10:27 .. -rw-r--r-- 1 stormacq admin 315 Jul 10 10:28 .gitignore -rw-r--r-- 1 stormacq admin 3421 Jul 10 10:28 amplifyconfiguration.json -rw-r--r-- 1 stormacq admin 1897 Jul 10 10:28 awsconfiguration.json
-
Löschen Sie Ihr Backend
Wenn Sie ein Backend für einen Test oder einen Prototyp oder einfach nur zu Lernzwecken erstellen, möchten Sie, genau wie beim Befolgen dieses Tutorials, die erstellten Cloud-Ressourcen löschen.
Obwohl die Nutzung dieser Ressourcen im Rahmen dieses Tutorials in das kostenlose Kontingent fällt, ist es eine bewährte Methode, ungenutzte Ressourcen in der Cloud zu bereinigen.
Um Ihr Amplify-Projekt zu bereinigen, führen Sie in einem Terminal den folgenden Befehl aus:
amplify delete
Nach einer Weile sehen Sie die untenstehende Meldung, die bestätigt, dass alle Cloud-Ressourcen gelöscht wurden.
✔ Project deleted in the cloud Project deleted locally.
Herzlichen Glückwunsch!
Sie haben eine Webanwendung auf AWS erstellt! Als großen nächsten Schritt sollten Sie tiefer in spezifische AWS-Technologien eintauchen und Ihre Anwendung auf die nächste Stufe bringen.