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
- Ele envia uma solicitação REST para excluir o registro do contato selecionado.
- 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.
- No Explorador do projeto do Xcode, abra Classes > SwiftUI > ContactDetailsView.swift.
- Role para a estrutura
ContactDetailView
. Ela começa com a linha que apresenta a seguinte sequência:struct ContactDetailView: View {
- Na definição de
var body: some View
, encapsule a declaraçãoList
com umVStack
. Remova a palavra-chavereturn
antes deList
. -
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) } } }
- 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) } } }
- Na parte superior da definição
ContactDetailView
, adicione uma variável de estado privado chamadadeleteWarning
e defina-a comofalse
. Essa variável controlará a apresentação da nossa folha de ação.struct ContactDetailView: View { @State private var deleteWarning = false
- Na ação Botão que você definiu, defina
deleteWarning
comotrue
. Essa atribuição ocorre quando o cliente toca no botão.Button(action:{ self.deleteWarning = true print("Delete Contact button tapped.")})
- 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! } ] ) } }
- 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.
- Faça login na sua organização de desenvolvedor e autorize o acesso aos dados.
- No modo de exibição Contas, clique em um nome qualquer da conta para ver sua lista de contatos.
- Clique em qualquer nome do contato para ver mais detalhes. Agora você está no modo de exibição ContactDetails.
- Clique no botão Excluir contato. Se não vir esse botão, verifique seu código novamente.
- 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".
- Não gosta das cores? Experimente alterar as propriedades
foregroundColor
ebackground
do seu Botão. Para ver as alterações, pare e reinicie o aplicativo.
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.
- No Explorador do projeto do Xcode, abra Classes > SwiftUI > ContactDetailsModel.swift.
- No código existente da classe
ContactDetailModel
, defina um novofunc
vazio chamadodeleteContact
. Esse novo método requer um único argumento,contact
, do tipoContact
e retornavoid
. -
class ContactDetailModel: ObservableObject{ @Published var contact: Contact init(with contact: Contact){ self.contact = contact } func deleteContact(contact: Contact) -> Void { } }
- Na parte superior da nova função, chame o método da API REST para definir
request
, seu objetoRestRequest
.func deleteContact(contact: Contact) -> Void { let request = RestClient.shared.requestForDelete(withObjectType: "Contact", objectId: contact.Id, apiVersion: nil) }
- 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 } }
- 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. -
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.") } } }
deleteContact(_:)
. Você consegue adivinhar onde fazer essa chamada? Lembra-se da folha de ação?- Abra o arquivo ContactDetailsView.swift.
- Role para a definição
.actionSheet
. Na matrizbuttons
da folha de ação, o botão.default
(o botão "OK") oferece um fechamento vazio. - Adicione suas chamadas no fechamento
.default
. Primeiro, crie uma instância deContactDetailModel
, passando no varcontact
local e, em seguida, chamedeleteContact(_:)
na instância do modelo. -
.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.
Recursos
- Guia do desenvolvedor: Como tratar respostas REST
- Guia do desenvolvedor: Modelo Swift nativo
- Guia do desenvolvedor: Como gerenciar os dados do modelo em seu aplicativo (Biblioteca de desenvolvedores do iOS)
- Link externo: Fechamentos (A linguagem de programação Swift)