
iOS App Extensions: expandindo seu aplicativo para o resto do celular
Há algum tempo, a Apple criou uma forma de expandir as capacidades dos aplicativos para além do próprio aplicativo, permitindo que desenvolvedores forneçam opções para interagir com outros aplicativos, além de possibilitar que o usuário acesse funcionalidades do aplicativo sem precisar abri-lo!
Esse tipo de programação foi batizada de “iOS App Extensions”. Estas extensões são partes do aplicativo e funcionam independentemente do próprio, como se fossem plug-ins com vida própria, e orbitam o próprio sistema Apple do celular permitindo modificações customizadas no sistema.
Isso tem permitido que os desenvolvedores iOS pensem além dos aplicativos, fornecendo ferramentas que criam uma User Experience mais completa a todos os usuários.
Hoje existem 23 templates para criação de extensões. Eles vão desde da edição de fotos, controle de arquivos, widget de ações para o dia à notificações e teclados customizados:

Cada tipo de extensão serve para uma tarefa específica. Para permitir que o usuário compartilhe algo do navegador diretamente no seu aplicativo, usamos uma “Share Extension”. Para notificações customizadas, inclusive permitindo controle de mídia e ações customizadas do usuário, utilizamos uma “Notification Content Extension”. Podemos até criar um teclado próprio da sua aplicação com o “Custom Keyboard Extension”. Devemos escolher a extensão baseada na funcionalidade que se desejamos implementar.
Cada extensão é ligada a um “extension point”, uma área do sistema única e com escopo fechado, que fornece API’s para criar extensões para aquela área. Uma extensão pode ter apenas um extension point, desta forma não é possível criar uma extensão genérica que funcione para mais de um escopo.
Abaixo a lista de extension points atual para iOS:


Como funcionam?
Apesar das extensões ficarem inclusas no aplicativo, na prática elas funcionam como binários independentes, rodando fora do aplicativo. No xCode, elas ficam como targets diferentes da aplicação, assim como testes unitários ou componentes.
Como a extensão não é um aplicativo, o ciclo de vida dela é diferente. Na maior parte dos casos, ela é instanciada pelo aplicativo que a contém assim que o usuário fornece a permissão para isso. Então, o sistema abre uma rota para a extensão independentemente do aplicativo e se comunica diretamente com ela, seja por opções customizadas de compartilhamento ou por UI de teclado: siri ou notificações. O acesso também depende do tipo de extension point que a extensão utiliza. Por fim, o sistema encerra o processo da extensão.

Exemplo de Extension com notificações — EverQuiz
Para demonstrar o poder das Extensions, fizemos um teste de notificação customizada e interativa. Esse tipo de implementação permite aos usuários interagirem com as notificações como se fossem parte do sistema operacional. Isso oferece um novo modo de se comunicar com os usuários de aplicativo:
Para desenvolver algo com essas capacidades, o primeiro passo é gerar extensões de ContentExtension (usado para notificação customizada) e ServiceExtension (permite conectar em serviços e carregar arquivos dentro da notificação):

Na ViewController, há um botão para registrar o usuário para a notificação. O evento de clique pede a permissão do cliente para notificações. Uma vez aceita, a permissão é registrada e uma notificação de classe “question” será disparada em 3 segundos:

Nesta etapa entra o ContentExtension: a extensão possui uma classe no arquivo .plist, chamado UNNotificationExtensionCategory, que basicamente diz o nome da classe de notificação que será interceptada para produzir o conteúdo customizado. Outras classes de notificação não serão interrompidas, e terão o comportamento padrão:

Dentro da notificação, possuímos uma função didReceiveNotification que recebe a notificação com a classe correspondente e a trata para a view em questão:

Todas as informações de notificação são passadas dentro do objeto UserInfo, assim recebemos todas as informações de fora e as utilizamos para montar a tela. Isso também funciona para notificações remotas, vindas do servidor para a aplicação. Por fim, instanciamos um player de vídeo com o arquivo passado para a notificação e aguardamos o usuário dar um play:

Substituímos as funções de InputView, InputAcessoryView e canBecomeFirstResponser para utilizar a view customizada de input como interação com o usuário:

E, por fim, no evento do vídeo terminar, a exibimos, iniciando o timer de 15 segundos e aguardando a interação.

No momento, utilizamos um arquivo de vídeo local do aplicativo. Se fosse necessário baixar a mídia antes de dar play, e no call-back de resposta enviaríamos a requisição para o servidor, usando o ServiceExtension como porta de comunicação. Abaixo um exemplo de implementação para download de vídeo da internet:

É possível pensar muito além de aplicativos clássicos contidos em si mesmos e começamos a imaginar como ir além e oferecer uma experiência de usuário completa para tudo o que o aplicativo se propõe a fazer. Por que não usarmos nosso aplicativo como gateway de compartilhamento? Por que não customizar a Siri com comandos de voz personalizados? Podemos usar um aplicativo como repositório de documentos que o Spotlight pode indexar, por que não fornecer um sistema de busca nativo? Basicamente, por que não inovar?
By: Alexandre Abreu