Conceitos básicos da AWS
Criar uma aplicação iOS
Criar uma aplicação iOS simples usando o AWS Amplify

adicionar api e banco de dados
Módulo 4: adicionar uma API GraphQL e um banco de dados
Neste módulo, você usará as bibliotecas e a CLI do Amplify para configurar e adicionar uma API GraphQL a seu aplicativo.
Introdução
Agora que criamos e configuramos o aplicativo com autenticação de usuário, vamos adicionar uma API e as operações Criar, Ler, Atualizar, Excluir (CRUD) em um banco de dados.
Neste módulo, você adicionará uma API ao aplicativo usando as bibliotecas e a CLI do Amplify. A API que você criará é uma API GraphQL que usa o AWS AppSync (um serviço GraphQL gerenciado), que tem o suporte do Amazon DynamoDB (um banco de dados NoSQL). Para ver uma introdução ao GraphQL, acesse esta página.
O aplicativo que criaremos é um aplicativo de notas que permite aos usuários criar, excluir e listar notas. Este exemplo dá uma boa ideia de como criar vários tipos comuns de aplicações CRUD+L (criação, leitura, atualização, exclusão e listas).
O que você aprenderá
- Criar e implantar uma API GraphQL
- Escrever um código front-end para interagir com a API
Conceitos principais
API – Fornece uma interface de programação que permite a comunicação e interação entre vários intermediários do software.
GraphQL – Uma linguagem de consulta e implementação de API no servidor baseada em uma representação de tipo da aplicação. A representação da API é declarada usando um esquema baseado no sistema de tipo do GraphQL. (Para saber mais sobre o GraphQL, acesseesta página.)
Tempo para a conclusão
20 minutos
Serviços usados
Implementação
-
Criar um serviço de API do GraphQL e um banco de dados
Para criar a API do GraphQL e o banco de dados de suporte, abra um terminal e execute este comando do diretório do projeto:
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
O editor de texto padrão que você escolheu quando inicializou o projeto (amplify init) é aberto com um esquema de dados predefinido.
Exclua o esquema e substitua-o pelo esquema de nosso aplicativo GraphQL:
type NoteData @model @auth (rules: [ { allow: owner } ]) { id: ID! name: String! description: String image: String }
O modelo de dados contém uma classe NoteData e 4 propriedades: o ID e o nome são obrigatórios; as strings de descrição e imagem são opcionais.
O transformador @model indica que desejamos criar um banco de dados para armazenar esses dados.
O transformador @auth adiciona regras de autenticação para permitir o acesso a esses dados. Para este projeto, desejamos que apenas o proprietário de NoteData tenha acesso a eles.
Ao concluir, não se esqueça de salvar.
-
Gerar código do cliente
Com base na definição de modelo de dados do GraphQL recém-criada, o Amplify gera código do cliente (código Swift) para representar os dados em nosso aplicativo.
Para gerar o código, no terminal,execute o seguinte comando:
amplify codegen models
Isso cria arquivos Swift no diretório amplify/generated/models directory, como pode ver em:
➜ 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
Importe estes arquivos no projeto Xcode: localize-os no Localizador e arraste e solte para o projeto no Xcode.
-
Implantar o serviço de API e banco de dados
Para implantar a API de back-end e o banco de dados que acabamos de criar, acesse o seu terminal e execute o comando:
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
Após alguns minutos, você deve ver uma mensagem de êxito:
✔ All resources are updated in the cloud GraphQL endpoint: https://yourid.appsync-api.eu-central-1.amazonaws.com/graphql
-
Adicionar biblioteca de cliente API ao projeto Xcode
Antes de acessar o código, você adiciona a biblioteca de API do Amplify às dependências do projeto. Abra o arquivo Podfile e adicione a linha com AmplifyPlugins/AWSAPIPlugin ou copie/cole o arquivo inteiro abaixo.
# 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
Em um terminal, execute o comando:
pod install
O comando leva alguns minutos para ser concluído. Você deve ver isto (os números da versão real podem variar):
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.
-
Inicializar bibliotecas do Amplify em tempo de execução
De volta ao Xcode, abra Backend.swift e adicione uma linha à sequência de inicialização do Amplify no método privado init(). Aparência do bloco de códigos completo:
// 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)") }
-
Adicionar elos entre o modelo de dados GraphQL e o modelo do aplicativo
Nosso projeto já tem um modelo de dados para representar uma nota. Tomei uma decisão de design para continuar a usar esse modelo e oferecer uma forma fácil de converter um NoteData em uma nota. Abra ContentView.swift e adicione este inicializador na classe Nota.
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! }
-
Adicionar métodos CRUD de API à classe back-end
Vamos adicionar 3 métodos para chamar nossa API: um método para consultar a nota, um método para criar uma nova nota e um método para excluir uma nota. Note que esses métodos funcionam no modelo de dados de aplicativo (Nota) para facilitar a interação a partir da interface do usuário. Esses métodos convertem de maneira transparente a nota em objetos NoteData do GraphQL.
Abra o arquivo Backend.swift e adicione o seguinte snippet ao final da 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)") } } }
No mesmo arquivo Backend.swift, atualize o método updateUserData(withSignInStatus:) para ter esta aparência:
// 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 = [] } } }
Agora só resta criar uma interface de usuário para criar uma nova nota e excluir uma nota da lista.
-
Adicionar um botão de edição para adicionar nota
Agora que os modelos back-end e de dados estão em vigor, a última etapa nesta seção é permitir que usuários criem uma nova nota e a excluam.
No Xcode, abra ContentView.swift
a. Na estrutura ContentView, adicione variáveis de estado vinculadas à interface de usuário.
// 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. Em qualquer ponto do arquivo, adicione uma estrutura de visualização para permitir que o usuário crie uma nova nota:
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. Adicione um botão + na barra de navegação para apresentar uma planilha para criar uma nota
De volta à estrutura ContentView, substitua navigationBarItems(leading SignOutButton()) por
.navigationBarItems(leading: SignOutButton(), trailing: Button(action: { self.showCreateNote.toggle() }) { Image(systemName: "plus") }) }.sheet(isPresented: $showCreateNote) { AddNoteView(isPresented: self.$showCreateNote, userData: self.userData)
-
Adicionar deslizar para excluir comportamento
Finalmente, em ContentView, adicione o comportamento 'deslizar para excluir': adicione o método .onDelete { } à estrutura 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) } }
-
Compilar e testar
Para verificar se tudo está funcionando conforme o esperado, compile e execute o projeto. Clique no menu Product (Produto) e selecione Run (Executar)ou digite ⌘R. Não deve aparecer nenhum erro.
Supondo que você ainda esteja conectado, o aplicativo inicia a lista vazia. Ele contém um botão + para adicionar uma nota. Toque no sinal +, toque em Create this Note (Criar esta Nota). A nota deve aparecer na lista.
Você pode fechar o AddNoteView extraindo-o. Note que, no simulador iOS, não é possível tocar em + uma segunda vez. Primeiro, você precisa 'extrair para atualizar' a lista.
Você pode excluir a nota, deslizando uma linha à esquerda.
Veja aqui o fluxo completo.