Hello, iOS – Aprofundamento

O passo a passo de início rápido, introduziu os procedimentos para compilar e executar um aplicativo básico do Xamarin.iOS. Agora é hora de desenvolver uma compreensão mais profunda de como funcionam os aplicativos iOS para que você possa criar programas mais sofisticados. Este guia examina as etapas no passo a passo Hello, iOS para habilitar a compreensão dos conceitos fundamentais do desenvolvimento de aplicativos iOS.

Este guia ajudará você a desenvolver as habilidades e o conhecimento necessário para criar um aplicativo iOS de uma única tela. Depois que trabalhar com ele, você deverá compreender as diferentes partes de um aplicativo Xamarin.iOS e como elas se encaixam.

Introdução ao Visual Studio para Mac

O Visual Studio para Mac é um IDE gratuito de código aberto que combina recursos do Visual Studio e do Xcode. Ele conta com um designer visual totalmente integrado, um editor de texto complementado com ferramentas de refatoração, um navegador de assembly, integração de código-fonte e muito mais. Este guia apresenta alguns recursos básicos do Visual Studio para Mac, mas, se você for novo no Visual Studio para Mac, confira a documentação Visual Studio para Mac.

O Visual Studio para Mac segue a prática do Visual Studio de organizar o código em soluções e projetos. Uma solução é um contêiner que pode conter um ou mais projetos. Um projeto pode ser um aplicativo (por exemplo, iOS ou Android), uma biblioteca com suporte, um aplicativo de teste e muito mais. No aplicativo Phoneword, um novo projeto de iPhone foi adicionado usando o modelo de Aplicativo de exibição única. A solução inicial tinha esta aparência:

Uma captura de tela da solução inicial

Introdução ao Visual Studio

O Visual Studio é um IDE avançado da Microsoft. Ele conta com um designer visual totalmente integrado, um editor de texto complementado com ferramentas de refatoração, um navegador de assembly, integração de código-fonte e muito mais. Este guia apresenta algumas funcionalidades básicas do Visual Studio com as Ferramentas de Xamarin para Visual Studio.

O Visual Studio organiza o código em soluções e projetos. Uma solução é um contêiner que pode conter um ou mais projetos. Um projeto pode ser um aplicativo (por exemplo, iOS ou Android), uma biblioteca com suporte, um aplicativo de teste e muito mais. No aplicativo Phoneword, um novo projeto de iPhone foi adicionado usando o modelo de Aplicativo de exibição única. A solução inicial tinha esta aparência:

Uma captura de tela da solução inicial

Anatomia de um aplicativo Xamarin.iOS

À esquerda está o Painel de soluções, que contém a estrutura de diretórios e todos os arquivos associados à solução:

O Painel de soluções, que contém a estrutura de diretórios e todos os arquivos associados à solução

À direita está o Painel da solução, que contém a estrutura de diretórios e todos os arquivos associados à solução:

O Painel da solução, que contém a estrutura de diretórios e todos os arquivos associados à solução

No passo a passo Hello, iOS, você criou uma solução chamada Phoneword e colocou um projeto iOS – Phoneword_iOS – dentro dela. Os itens dentro do projeto incluem:

  • Referências – contém os assemblies necessários para compilar e executar o aplicativo. Expanda o diretório para ver referências a assemblies do .NET como System, System.Core e System.Xml, bem como uma referência ao assembly Xamarin.iOS.
  • Pacotes – o diretório de pacotes contém pacotes do NuGet prontos.
  • Recursos – a pasta de recursos armazena outras mídias.
  • Main.cs – isso contém o ponto de entrada principal do aplicativo. Para iniciar o aplicativo, o nome da classe principal do aplicativo, a AppDelegate, é passado.
  • AppDelegate.cs – esse arquivo contém a classe principal do aplicativo e é responsável por criar a janela, criar a interface do usuário e escutar eventos do sistema operacional.
  • Main.Storyboard – o storyboard contém o design visual da interface do usuário do aplicativo. Arquivos de storyboard abertos em um editor gráfico chamado Designer iOS.
  • ViewController.cs – o controlador de exibição aciona a tela (exibição) que um usuário vê e toca. O controlador de exibição é responsável por lidar com as interações entre o usuário e a exibição.
  • ViewController.designer.cs – o designer.cs é um arquivo gerado automaticamente que serve como o elo entre controles na exibição e suas representações em código no controlador de exibição. Como esse é um arquivo de conexão interna, o IDE substituirá todas as alterações manuais e, na maioria das vezes, esse arquivo poderá ser ignorado.
  • Info.plistInfo.plist é onde as propriedades do aplicativo, como o nome do aplicativo, ícones, imagens de inicialização, entre outros, são definidos. Esse é um arquivo poderoso e uma introdução completa sobre ele está disponível no guia Como trabalhar com listas de propriedades.
  • Entitlements.plist – a lista de propriedades de direito nos permite especificar as funcionalidades do aplicativo (também chamadas de tecnologias de repositório de aplicativo) como iCloud, PassKit e muito mais. Mais informações sobre Entitlements.plist podem ser encontradas no guia Como trabalhar com listas de propriedades. Para obter uma introdução geral a direitos, consulte o guia Provisionamento de dispositivos.

Conceitos básicos de aplicativo e arquitetura

Antes que um aplicativo iOS possa carregar uma interface do usuário, duas coisas precisam estar prontas. Primeiro, o aplicativo precisa definir um ponto de entrada – o primeiro código que é executado quando o processo do aplicativo é carregado na memória. Em segundo lugar, é necessário definir uma classe para manipular eventos em todo o aplicativo e interagir com o sistema operacional.

Esta seção estuda as relações ilustradas no diagrama a seguir:

As relações dos conceitos básicos de arquitetura e aplicativo estão ilustradas neste diagrama

Método Principal

O ponto de entrada principal de um aplicativo iOS é a classe Application. A classe Application é definida no arquivo Main.cs e contém um método Main estático. Ele cria uma nova instância do aplicativo Xamarin.iOS e passa o nome da classe Delegado do aplicativo que manipulará eventos do sistema operacional. O código de modelo do método estático Main aparece abaixo:

using System;
using UIKit;

namespace Phoneword_iOS
{
    public class Application
    {
        static void Main (string[] args)
        {
            UIApplication.Main (args, null, "AppDelegate");
        }
    }
}

Delegado do aplicativo

No iOS, a classe Delegado do aplicativo manipula eventos de sistema; essa classe reside dentro de AppDelegate.cs. A classe AppDelegate gerencia a janela do aplicativo. A Janela é uma única instância da classe UIWindow, que serve como um contêiner para a interface do usuário. Por padrão, um aplicativo obtém apenas uma janela na qual carregar seu conteúdo e a Janela é anexada a uma tela (instância única de UIScreen) que fornece o retângulo delimitador correspondente às dimensões da tela do dispositivo físico.

O AppDelegate também é responsável por assinar atualizações do sistema sobre eventos do aplicativo importantes, por exemplo, quando a inicialização do aplicativo é concluída ou quando a memória é insuficiente.

O código do modelo para AppDelegate é apresentado abaixo:

using System;
using Foundation;
using UIKit;

namespace Phoneword_iOS
{

    [Register ("AppDelegate")]
    public partial class AppDelegate : UIApplicationDelegate
    {
        public override UIWindow Window {
            get;
            set;
        }

        ...
    }
}

Depois que o aplicativo define sua janela, ele pode começar a carregar a interface do usuário. A próxima seção explora a criação da interface do usuário.

Interface do usuário

A interface do usuário de um aplicativo iOS é como uma vitrine – o aplicativo normalmente obtém uma Janela, mas ele pode preencher a janela com o número de objetos que precisar e as disposições e objetos podem ser alterados dependendo do que o aplicativo deseja exibir. Os objetos nesse cenário – as coisas que o usuário vê – são chamados de exibições. Para criar uma única tela em um aplicativo, as exibições são empilhadas umas sobre as outras em uma hierarquia de exibição de conteúdo e a hierarquia é gerenciada por um único controlador de exibição. Aplicativos com várias telas têm várias hierarquias de exibição de conteúdo, cada uma com seu próprio controlador de exibição; o aplicativo coloca as exibições na janela para criar uma hierarquia de exibição de conteúdo diferente com base na tela na qual o usuário está.

Para obter mais detalhes sobre como criar uma interface de usuário usando Storyboards, consulte a seção Projetando com Storyboards da Visão geral do Xcode na Biblioteca de desenvolvedores iOS da Apple.

O diagrama a seguir ilustra as relações entre a janela, exibições, subexibições e controlador de exibição que levam a interface do usuário para a tela do dispositivo:

As relações entre a janela, as exibições, as subexibições e o controlador de exibição

A próxima seção discute como trabalhar com exibições no código e aprender programação voltada à interação do usuário usando os controladores de exibição e o ciclo de vida da exibição.

Controladores de exibição e ciclo de vida da exibição

Cada hierarquia de exibição de conteúdo tem um controlador de exibição correspondente para promover a interação do usuário. A função do controlador de exibição é gerenciar as exibições na hierarquia de exibição de conteúdo. O controlador de exibição não é parte da hierarquia de exibição de conteúdo e não é um elemento na interface. Em vez disso, ele fornece o código que promove as interações do usuário com os objetos na tela.

Controladores de exibição e storyboards

O controlador de exibição é representado em um storyboard como uma barra na parte inferior da cena. Selecionar o controlador de exibição exibe suas propriedades no Painel de Propriedades:

Ao selecionar o controlador de exibição, as propriedades são exibidas no Painel Propriedades

Uma classe de controlador de exibição personalizada para a hierarquia de Exibição de conteúdo representada por essa cena pode ser definida por meio da edição da propriedade Classe, na seção Identidade do Painel de Propriedades. Por exemplo, nosso aplicativo Phoneword define o ViewController como o controlador de exibição para nossa primeira tela, conforme ilustrado pela captura de tela abaixo:

O aplicativo Phoneword define o ViewController como o controlador de exibição

O controlador de exibição é representado em um storyboard como uma barra na parte inferior da cena. Com a seleção do controlador de exibição, as propriedades são exibidas no Painel Propriedades:

Ao selecionar o controlador de exibição, as propriedades são exibidas no Painel Propriedades

Uma classe de controlador de exibição personalizada para a hierarquia de exibição de conteúdo representada por essa cena pode ser definida por meio da edição da propriedade Classe, na seção Identidade do Painel Propriedades. Por exemplo, nosso aplicativo Phoneword define o ViewController como o controlador de exibição para nossa primeira tela, conforme ilustrado pela captura de tela abaixo:

O aplicativo Phoneword define o ViewController como o controlador de exibição

Isso vincula a representação do storyboard do controlador de exibição para a classe C# ViewController. Abra o arquivo ViewController.cs e observe que o controlador de exibição é uma subclasse de UIViewController, conforme ilustrado pelo código a seguir:

public partial class ViewController : UIViewController
{
    public ViewController (IntPtr handle) : base (handle)
    {

    }
}

O ViewController agora conduz as interações da hierarquia de exibição de conteúdo associadas a esse controlador de exibição no storyboard. Em seguida, você aprenderá sobre a função do controlador de exibição de gerenciar as exibições por meio da introdução de um processo chamado ciclo de vida de exibição.

Observação

Para telas puramente visuais que não exigem interação do usuário, a propriedade Classe pode ser deixada em branco no Painel Propriedades. Isso define a classe subjacente do controlador de exibição como a implementação padrão de um UIViewController, o que é apropriado se você não planeja adicionar código personalizado.

Ciclo de vida de exibição

O controlador de exibição é responsável por carregar e descarregar hierarquias de exibição de conteúdo da janela. Quando algo importante acontece em uma exibição na hierarquia de exibição de conteúdo, o sistema operacional notifica o controlador de exibição por meio de eventos no ciclo de vida de exibição. Substituindo métodos do ciclo de vida de exibição, você pode interagir com os objetos na tela e criar uma interface do usuário dinâmica e responsiva.

Estes são os métodos de ciclo de vida básicos e suas funções:

  • ViewDidLoad – chamado uma vez na primeira vez que o controlador de exibição carrega sua hierarquia de exibição de conteúdo na memória. Esse é um bom lugar para realizar a configuração inicial, porque é quando as subexibições se tornam disponíveis no código pela primeira vez.
  • ViewWillAppear – chamado sempre que a exibição de um controlador de exibição está prestes a ser adicionada a uma hierarquia de exibição de conteúdo e aparecer na tela.
  • ViewWillDisappear – chamado sempre que a exibição de um controlador de exibição está prestes a ser removida a uma hierarquia de exibição de conteúdo e desaparecer da tela. Esse evento de ciclo de vida é usado para limpeza e para salvar estados.
  • ViewDidAppear e ViewDidDisappear – chamados quando uma exibição é adicionada ou removida da hierarquia de exibição de conteúdo, respectivamente.

Quando o código personalizado é adicionado a qualquer estágio do ciclo de vida, a implementação base desse método de ciclo de vida deve ser substituída. Isso é realizado usando-se para derivação o método de ciclo de vida existente (que já tem algum código anexado a ele) e estendendo-o com código adicional. A implementação base é chamada de dentro do método para certificar-se de que o código original é executado antes do novo código. Um exemplo disso é demonstrado na próxima seção.

Para obter mais informações sobre como trabalhar com controladores de exibição, veja o Guia de programação de controlador de exibição para iOS da Apple e a referência do UIViewController.

Respondendo à interação do usuário

A função mais importante do controlador de exibição é responder a interações do usuário como pressionamentos de botão, navegação e muito mais. A maneira mais simples de manipular a interação do usuário é conectar um controle para escutar a entrada do usuário e anexar um manipulador de eventos para responder à entrada. Por exemplo, um botão pode ser conectado para responder a um evento de toque, conforme demonstrado no aplicativo Phoneword.

Vamos explorar como isso funciona. No projeto Phoneword_iOS, um botão chamado TranslateButton foi adicionado à hierarquia de exibição de conteúdo:

Um botão chamado TranslateButton foi adicionado à hierarquia de exibição de conteúdo

Quando uma saída de referência é criada usando o Xcode Interface Builder, o Xcode Sync a mapeia automaticamente para um controle no ViewController.designer.cs, disponibilizando a dentro da TranslateButtonViewController classe. Controles serão disponibilizados primeiro no estágio ViewDidLoad do ciclo de vida de exibição, portanto, esse método de ciclo de vida é usado para responder ao toque do usuário:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // wire up TranslateButton here
}

O aplicativo Phoneword usa um evento de toque chamado TouchUpInside para ouvir o toque do usuário. TouchUpInside escuta um evento toque para cima (levantando o dedo para fora da tela) que ocorre após um toque para baixo (tocando o dedo na tela) dentro dos limites do controle. O oposto de TouchUpInside é o evento TouchDown, que é acionado quando o usuário pressiona um controle. O evento TouchDown captura muito ruído e não dá ao usuário nenhuma opção de cancelar a interatividade ao deslizar o dedo para fora do controle. TouchUpInside é a maneira mais comum de responder a um toque no botão e cria a experiência que o usuário espera ter ao pressionar um botão. Mais informações sobre isso estão disponíveis nas Diretrizes de Interface Humana iOS da Apple.

O aplicativo tratou o TouchUpInside evento com um lambda, mas também seria possível usar um manipulador de evento nomeado ou delegado. O código do último botão era semelhante ao seguinte:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    string translatedNumber = "";

    TranslateButton.TouchUpInside += (object sender, EventArgs e) => {
      translatedNumber = Core.PhonewordTranslator.ToNumber(PhoneNumberText.Text);
      PhoneNumberText.ResignFirstResponder ();

      if (translatedNumber == "") {
        CallButton.SetTitle ("Call", UIControlState.Normal);
        CallButton.Enabled = false;
      } else {
        CallButton.SetTitle ("Call " + translatedNumber, UIControlState.Normal);
        CallButton.Enabled = true;
      }
  };
}

Conceitos adicionais introduzidos no Phoneword

O aplicativo Phoneword introduziu vários conceitos que não foram abordados neste guia. Esses conceitos incluem:

  • Alterar o texto do botão – o aplicativo Phoneword demonstrou como alterar o texto de um botão chamando SetTitle no botão e passando o novo texto e o estado do controle do botão. Por exemplo, o código a seguir altera o texto do CallButton para “Call”:

    CallButton.SetTitle ("Call", UIControlState.Normal);
    
  • Habilitar e desabilitar botõesbotões podem estar em um estado Enabled ou Disabled. Um botão desabilitado não responderá à entrada do usuário. Por exemplo, o seguinte código desabilita o CallButton:

    CallButton.Enabled = false;
    

    Para obter mais informações sobre botões, veja o guia Botões.

  • Ignorar o teclado – quando a usuário toca no campo de texto, o iOS exibe o teclado para permitir que o usuário insira a entrada. Infelizmente, não há nenhuma funcionalidade interna para ignorar o teclado. O código a seguir é adicionado ao TranslateButton para ignorar o teclado quando o usuário pressiona TranslateButton:

    PhoneNumberText.ResignFirstResponder ();
    

    Para ver outro exemplo de como ignorar o teclado, veja o guia Ignorar o teclado.

  • Realizar chamada telefônica com URL – no aplicativo Phoneword, um esquema de URL da Apple é usado para inicializar o aplicativo de telefone do sistema. O esquema de URL personalizado consiste em uma "tel:" prefixo e o número de telefone traduzido, conforme ilustrado pelo código a seguir:

    var url = new NSUrl ("tel:" + translatedNumber);
    if (!UIApplication.SharedApplication.OpenUrl (url))
    {
        // show alert Controller
    }
    
  • Mostrar um alerta – quando um usuário tenta fazer uma chamada telefônica em um dispositivo que não oferece suporte a chamadas – por exemplo, o simulador ou um iPod Touch – uma caixa de diálogo de alerta é exibida para avisar ao usuário que a chamada telefônica não pode ser realizada. O código a seguir cria e popula um controlador de alerta:

    if (!UIApplication.SharedApplication.OpenUrl (url)) {
                    var alert = UIAlertController.Create ("Not supported", "Scheme 'tel:' is not supported on this device", UIAlertControllerStyle.Alert);
                    alert.AddAction (UIAlertAction.Create ("Ok", UIAlertActionStyle.Default, null));
                    PresentViewController (alert, true, null);
                }
    

    Para obter mais informações sobre exibições de alertas do iOS, consulte a receita do controlador de alerta.

Testes, implantação e toques finais

Ambos o Visual Studio para Mac e o Visual Studio oferecem várias opções para testar e implantar um aplicativo. Esta seção aborda as opções de depuração, demonstra o teste de aplicativos no dispositivo e apresenta ferramentas para a criação de ícones do aplicativo personalizados e imagens de inicialização.

Ferramentas de depuração

Algumas vezes, Problemas no código do aplicativo são difíceis de diagnosticar. Para ajudar a diagnosticar problemas de código complexos, você poderia definir um ponto de interrupção, examinar o código passo a passo ou enviar informações para a janela de Log.

Implantar em um dispositivo

O Simulador iOS é uma maneira rápida de testar um aplicativo. O Simulador tem uma série de otimizações úteis para testes, inclusive local fictício, simulação de movimento e muito mais. No entanto, os usuários não consumirão aplicativo final em um simulador. Todos os aplicativos devem ser testados em dispositivos reais antecipadamente e com frequência.

Um dispositivo leva tempo para provisionar e requer uma Conta de Desenvolvedor Apple. O guia Provisionamento de dispositivo fornece instruções completas de como preparar um dispositivo para o desenvolvimento.

Observação

Atualmente, devido a um requisito da Apple, é necessário ter um certificado de desenvolvimento ou uma identidade de assinatura para compilar o código para um dispositivo físico ou para o simulador. Siga as etapas no guia Provisionamento de Dispositivo para configurar isso.

Depois que o dispositivo é configurado você pode implantar para ele conectando-o, alterando o destino na barra de ferramentas de build para o dispositivo iOS e pressionando Iniciar ( Reproduzir) conforme ilustrado pela captura de tela a seguir:

Pressionar Iniciar/Reproduzir

Pressionar Iniciar/Reproduzir

O aplicativo será implantado no dispositivo iOS:

O aplicativo será implantado no dispositivo iOS e executado

Gerar ícones personalizados e imagens de inicialização

Nem todo mundo tem um designer disponível para criar os ícones personalizados e iniciar imagens que um aplicativo precisa para se destacar. Aqui estão várias abordagens alternativas para gerar o trabalho artístico do aplicativo personalizado:

  • Pixelmator – uma imagem versátil editando o aplicativo para Mac que custa aproximadamente US$ 30.
  • Fiverr – escolha dentre uma variedade de designers para criar um ícone definido para você, com valores partindo de US$ 5. Mesmo que os resultados com ele nem sempre sejam os esperados, trata-se de um bom recurso para quem precisa criar ícones rapidamente
  • Visual Studio – você pode usar isso para criar um conjunto de ícones simples para seu aplicativo diretamente no IDE.
  • Fiverr – escolha dentre uma variedade de designers para criar um ícone definido para você, com valores partindo de US$ 5. Mesmo que os resultados com ele nem sempre sejam os esperados, trata-se de um bom recurso para quem precisa criar ícones rapidamente

Para obter mais informações sobre requisitos e tamanhos de imagem de inicialização e de ícone, consulte o guia Como trabalhar com imagens.

Resumo

Parabéns! Agora você tem uma compreensão sólida dos componentes de um aplicativo Xamarin.iOS, bem como das ferramentas usadas para criá-los. No próximo tutorial na série Introdução, você estenderá nosso aplicativo para lidar com várias telas. Ao longo do caminho você implementará um controlador de navegação, aprenderá sobre o Storyboard Segues e introduzirá o padrão MVC (Model, View, Controller) à medida que estende o aplicativo para gerenciar várias telas.