Conceitos básicos da AWS

Criar uma aplicação iOS

Criar uma aplicação iOS simples usando o AWS Amplify

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.

    iOSTutorial-Module4-Step1
  • 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.

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

Conclusão

Você criou um aplicativo iOS! Usando o AWS Amplify, você adicionou uma API GraphQL e configurou as funções de criação, leitura e exclusão no seu aplicativo.

No próximo módulo, adicionaremos interface do usuário e comportamento para gerenciar fotos.

Este módulo foi útil?

Agradecemos a sua atenção
Gostaríamos de saber do que você gostou.
Fechar
Desculpe por ter desapontado
Encontrou algo desatualizado, confuso ou incorreto? Envie seus comentários para nos ajudar a melhorar este tutorial.
Fechar

Adicionar armazenamento