Skip to main content
Join the Agentforce Hackathon on Nov. 18-19 to compete for a $20,000 Grand Prize. Sign up now. Terms apply.

Modificar o aplicativo nativo forceios

Objetivos de aprendizagem

Após concluir esta unidade, você estará apto a:

  • Adicionar um botão que permite que os usuários excluam um contato do Salesforce.
  • Adicionar uma nova solicitação REST ao aplicativo modelo iOS nativo.
  • Tratar da resposta REST.

Acompanhar com o Trail Together

Deseja acompanhar um especialista enquanto trabalha nesta etapa? Veja este vídeo que faz parte da série Trail Together.

(Este clipe começa na marca dos 18:11 minutos, caso você queira retroceder e ver o início da etapa novamente.)

Como personalizar um aplicativo Swift forceios

O modelo usado pelo forceios para criar aplicativos Swift exibe uma lista de nomes de contas de uma organização do Salesforce. A partir dessa lista, você pode visualizar detalhes de uma conta selecionada e, a partir daí, uma lista dos contatos da conta. Em seguida, você pode selecionar um contato para visualizar seus detalhes. Os clientes não podem usar o aplicativo para interagir com os dados. Só é possível visualizá-los. Vamos melhorar um pouco um aplicativo Swift forceios adicionando um botão à visualização de detalhes do contato que permite ao usuário excluir o registro desse contato. Se o usuário tocar nesse botão, o código responderá da seguinte forma:
  1. Ele envia uma solicitação REST para excluir o registro do contato selecionado.
  2. Ele pede ao cliente para confirmar a exclusão.

Para fazer esse exercício, você pode usar o espaço de trabalho do Mobile SDK criado na unidade de abertura do iOS nativo.

Exibições e modelos

Se você olhar para a pasta Classes do projeto do Xcode, verá duas subpastas: SwiftUI e Modelos. Como seus nomes indicam, essas pastas expressam a arquitetura do modelo de exibição dos aplicativos SwiftUI. 

  • A pasta SwiftUI contém definições de exibição (também conhecidas como “material da interface do usuário”). Na maioria das vezes, esses arquivos contêm configurações de layout de SwiftUI e seus atributos visuais. Tipicamente, as visualizações SwiftUI são definidas como estruturas.
  • A pasta Modelos contém a funcionalidade de dados que potencializa as visualizações SwiftUI. As visualizações chamam modelos para executar tarefas de dados, como obter nomes de contas do Salesforce ou excluir um registro de contato. Os modelos geralmente incluem uma definição de classe central para definir a funcionalidade e, talvez, algumas estruturas para a organização de dados.

Cada modelo nesse aplicativo de modelo compartilha um prefixo de nome de arquivo com sua exibição emparelhada. Por exemplo, ContactDetailsModel.swift fornece o modelo para ContactDetailsView.swift.

Adicionar o botão Excluir

Vamos começar pelo princípio! Vamos começar implementando a questão estética, ou visual. Podemos projetar, codificar e testar o botão Excluir contato antes de torná-lo totalmente funcional. 

A estrutura ContactDetailView do modelo é uma lista agregada de itens definidos em outro lugar nesse arquivo. Para manter o botão e esse elemento List pré-existente independente um do outro, crie um contêiner VStack para envolver ambos. Este contêiner diz ao iOS para alinhar seus elementos verticalmente à medida que eles são dispostos no código. Para fazer com que o botão Excluir apareça na parte inferior da cena, por exemplo, coloque o botão após List no VStack. 

Em SwiftUI, os construtores do Botão exigem um argumento action. Essa ação é executada quando o cliente toca no botão. Por enquanto, enviaremos uma mensagem para o console do Xcode confirmando o toque do cliente.

  1. No Explorador do projeto do Xcode, abra Classes > SwiftUI > ContactDetailsView.swift.
  2. Role para a estrutura ContactDetailView. Ela começa com a linha que apresenta a seguinte sequência: 
    struct ContactDetailView: View {
  3. Na definição de var body: some View, encapsule a declaração List com um VStack. Remova a palavra-chave return antes de List.
  4. var body: some View { 
        VStack(alignment: .center, spacing: 3) {
            List {
                FieldView(label: "First Name", value: contact.FirstName)
                FieldView(label: "Last Name", value: contact.LastName)
                FieldView(label: "Email", value: contact.Email)
                FieldView(label: "Phone Number", value: contact.PhoneNumber)
                AddressView(contact: contact)
            }
        }
    }
  5. Abaixo do bloco List, pouco antes de fechar o parênteses do VStack, adicione o bloco Button.
    var body: some View { 
        VStack(alignment: .center, spacing: 3) {
            List {
                FieldView(label: "First Name", value: contact.FirstName)
                FieldView(label: "Last Name", value: contact.LastName)
                FieldView(label: "Email", value: contact.Email)
                FieldView(label: "Phone Number", value: contact.PhoneNumber)
                AddressView(contact: contact)
            }                  
            Button(action:{
                print("Delete Contact button tapped.")})
            {
                Text("Delete Contact")
                .bold()
                .font(.title)
                .padding()
                .foregroundColor(Color.white)
                .background(Color.gray)
            }
        }
    }
Se você executasse o aplicativo agora, veria o botão na parte inferior da visualização, mas não faria nada relevante. Se você tocar no aplicativo, ele apenas imprimirá uma mensagem informativa para você, o desenvolvedor, no Xcode.

Os clientes correm o risco de tocar no botão Excluir contato sem querer, por exemplo, se estiverem em transportes públicos que balançam muito enquanto usam seu aplicativo. Para proteger os dados do cliente, convém pedir confirmação antes de excluir um contato. Vamos adicionar uma folha de ação para lembrar os clientes que eles estão excluindo o registro de contato na organização do Salesforce. Uma folha de ação é como um alerta com vários botões de ação. Nesse caso, dois botões, OK e Cancelar, são suficientes. Se o cliente clicar no botão Cancelar, o aplicativo abandonará a solicitação de exclusão.
  1. Na parte superior da definição ContactDetailView, adicione uma variável de estado privado chamada deleteWarning e defina-a como false. Essa variável controlará a apresentação da nossa folha de ação.
    struct ContactDetailView: View {
        @State private var deleteWarning = false
  2. Na ação Botão que você definiu, defina deleteWarning como true. Essa atribuição ocorre quando o cliente toca no botão. 
    Button(action:{
            self.deleteWarning = true
            print("Delete Contact button tapped.")})
  3. Após fechar o parênteses do bloco VStack, adicione a definição da folha de ação.
    .actionSheet(isPresented: $deleteWarning) {
        ActionSheet(title: Text("Deleting Contact"),
            message: Text("This action deletes this contact in your org."),
            buttons: [
                .cancel {},
                .default(Text("OK")) {
                    // TO DO
                }
            ]
        )
    }

Veja sua definição de exibição até esse ponto.

var body: some View {
    VStack(alignment: .center, spacing: 3) {
        List {
            FieldView(label: "First Name", value: contact.FirstName)
            FieldView(label: "Last Name", value: contact.LastName)
            FieldView(label: "Email", value: contact.Email)
            FieldView(label: "Phone Number", value: contact.PhoneNumber)
            AddressView(contact: contact)
        }
        Button(action:{
            self.deleteWarning = true
            print("Delete Contact button tapped.")})
        {
            Text("Delete Contact")
            .bold()
            .font(.title)
            .padding()
            .foregroundColor(Color.white)
            .background(Color.gray)
        }
    }
    .actionSheet(isPresented: $deleteWarning) {
        ActionSheet(title: Text("Deleting Contact"),
            message: Text("This action deletes this contact in your org."),
            buttons: [
                .cancel {},
                .default(Text("OK")) {
                    // TODO! 
                }
            ]
        )
    }
}
Você adicionou uma boa quantidade de código. Vamos testar a configuração.
  1. Clique em Executar para verificar se há erros no aplicativo. Se, até o momento, seu trabalho não tiver erros, um simulador do iPhone será lançado e, após alguns segundos, exibirá a tela de login do Salesforce.
  2. Faça login na sua organização de desenvolvedor e autorize o acesso aos dados.
  3. No modo de exibição Contas, clique em um nome qualquer da conta para ver sua lista de contatos.
  4. Clique em qualquer nome do contato para ver mais detalhes. Agora você está no modo de exibição ContactDetails.
  5. Clique no botão Excluir contato. Se não vir esse botão, verifique seu código novamente.
  6. Para confirmar se o botão está configurado corretamente, verifique o console de depuração do Xcode para obter uma linha que diz "botão Excluir contato foi tocado".
  7. Não gosta das cores? Experimente alterar as propriedades foregroundColor e background do seu Botão. Para ver as alterações, pare e reinicie o aplicativo.
Nota

Durante a criação e execução do seu aplicativo, é possível que você veja o seguinte aviso (com diferentes IDs) no Xcode. Se vir o aviso, ignore-o com segurança. 

[LayoutConstraints] Unable to simultaneously satisfy constraints.
                                   Probably at least one of the constraints in the following list is one you don't want. 
                                      Try this: 
                                      (1) look at each constraint and try to figure out which you don't expect; 
                                      (2) find the code that added the unwanted constraint or constraints and fix it. 
                                      (
                                          "<NSLayoutConstraint:0x600003c4ecb0 UIView:0x7fca9dd27330.width == - 16   (active)>"
                                      )
                                      Will attempt to recover by breaking constraint 
                                          <NSLayoutConstraint:0x600003c4ecb0 UIView:0x7fca9dd27330.width == - 16   (active)>

Para obter mais informações, consulte essa discussão do Stack Overflow.

Agora, vamos fazer com que esse botão realize seu trabalho homônimo: Excluir o registro Contato. 

Enviar a Solicitação de exclusão para o Salesforce

Para excluir um registro Contato, adicione código ao arquivo de origem do modelo. Se você navegar pelo arquivo Classes/Models/ContactDetailModel.swift, verá que a classe ContactDetailModel é mínima.

class ContactDetailModel: ObservableObject{
    @Published var contact: Contact
    init(with contact: Contact){
        self.contact = contact
    }
}

Você pode usar o membro Id da propriedade self.contact para identificar o registro atualmente exibido.

Para criar a solicitação REST, chame o método RestClient.shared.requestForDelete(withObjectType:objectId:apiVersion:). Essa solicitação é incomum entre as solicitações de API do Salesforce porque, se bem-sucedida, não tem nada importante para retornar ao chamador. Como seu aplicativo não receberá um pacote de dados para analisar e implantar, você pode tratar da resposta REST em um simples fechamento de conclusão. 

  1. No Explorador do projeto do Xcode, abra Classes > SwiftUI > ContactDetailsModel.swift.
  2. No código existente da classe ContactDetailModel, defina um novo func vazio chamado deleteContact. Esse novo método requer um único argumento, contact, do tipo Contact e retorna void.
  3. class ContactDetailModel: ObservableObject{
        @Published var contact: Contact
        init(with contact: Contact){
            self.contact = contact
        }
        func deleteContact(contact: Contact) -> Void {
        }
    }
  4. Na parte superior da nova função, chame o método da API REST para definir request, seu objeto RestRequest.
    func deleteContact(contact: Contact) -> Void {
        let request = RestClient.shared.requestForDelete(withObjectType: "Contact", 
                                                               objectId: contact.Id, 
                                                             apiVersion: nil)
    }
  5. Para enviar a solicitação ao Salesforce, chame a função RestClient.shared.send(request:_:). O primeiro argumento é a solicitação previamente formatada que você criou. Para o segundo argumento, inclua um fechamento de conclusão. 
    func deleteContact(contact: Contact) -> Void {
        let request = RestClient.shared.requestForDelete(withObjectType: "Contact", 
                                                               objectId: contact.Id, 
                                                             apiVersion: nil)
        RestClient.shared.send(request: request) {result in
        }
    }
  6. Preencha o fechamento de conclusão com um bloco switch que trata dois casos: .success(_) e .failure(_). Para esse exercício simples, imprima uma mensagem de status para cada resultado no console de depuração do Xcode.
  7. func deleteContact(contact: Contact) -> Void {
        let request = RestClient.shared.requestForDelete(withObjectType: "Contact", 
                                                               objectId: contact.Id, 
                                                             apiVersion: nil)
        RestClient.shared.send(request: request) {result in
            switch result {
                case .success(_):
                    print("Contact deleted.")
                case .failure(_):
                    print("Your attempt to delete this contact could not be completed. This is possibly because it is associated with cases or other dependencies.")
            }
        }
    }
E você concluiu a classe de modelo! Você codificou a funcionalidade do Mobile SDK para excluir um registro do Salesforce. Resta apenas fazer uma coisa: chamar o novo método deleteContact(_:). Você consegue adivinhar onde fazer essa chamada? Lembra-se da folha de ação?
  1. Abra o arquivo ContactDetailsView.swift.
  2. Role para a definição .actionSheet. Na matriz buttons da folha de ação, o botão .default (o botão "OK") oferece um fechamento vazio.
  3. Adicione suas chamadas no fechamento .default. Primeiro, crie uma instância de ContactDetailModel, passando no var contact local e, em seguida, chame deleteContact(_:) na instância do modelo.
  4. .actionSheet(isPresented: $deleteWarning) {
        ActionSheet(title: Text("Deleting Contact"),
            message: Text("This action deletes this contact in your org."),
            buttons: [
                .cancel {},
                .default(Text("OK")) {
                    let model = ContactDetailModel(with: contact)
                    model.deleteContact(contact: contact) 
                }
            ]
        )
    }

Esse produto acabado fica aquém da qualidade de produção. Os clientes não saberão se sua exclusão foi bem-sucedida até que retornem modo de exibição de lista Contatos e vejam se o contato já não está listado. Ou, se descobrirem que o contato não desapareceu da exibição, não terão qualquer pista do que deu errado. Uma maneira de corrigir essa lacuna seria substituir a instrução RestClient.shared.send(request:_:) com um editor Combine e publicar o resultado da chamada de exclusão. Em seguida, em ContactDetailView, mostre o resultado ao cliente na interface do usuário da exibição ou em uma caixa de alerta.

Experimente!

Você já está pronto para criar e executar seu código no simulador de iOS. Observe que você recebe uma resposta de erro quando tenta excluir um contato padrão no banco de dados da Developer Edition. Esses erros ocorrem porque cada contato que vem pré-empacotado em uma organização Developer Edition é pai de outros registros. Para se preparar para o teste, faça login na sua organização Developer Edition e crie um ou mais contatos de teste que não tenham outros registros.

Compartilhe seu feedback do Trailhead usando a Ajuda do Salesforce.

Queremos saber sobre sua experiência com o Trailhead. Agora você pode acessar o novo formulário de feedback, a qualquer momento, no site Ajuda do Salesforce.

Saiba mais Continue compartilhando feedback