Pensando em complementar nossos conhecimentos, o objetivo desse artigo é mostrar como consumir uma API em GraphQL no iOS. Já te digo que existem diversas maneiras para implementar esse padrão, mas vamos abordar seu uso com o Apollo framework. o Apollo iOS SDK é um projeto Open Source e está disponível no GitHub por aqui.
Sobre o Apollo framework
Por que o Apollo? Simples: ele fornece todo o necessário para criar solicitações ao servidor! Ele também se baseia em um arquivo schema disponibilizado por uma API GraphQL para fazer toda a análise, normalização e cache de dados.
Aqui estão os principais motivos para escolhê-lo.
Vantagens do Apollo
Multiplataforma
O Apollo está disponível para muitas plataformas como front-end, server, iOS e Android. Todas essas plataformas seguem os mesmos conceitos, possuindo apenas particularidades linguísticas próprias.
Baseado em um schema
Utiliza um GraphQL schema disponível a partir do servidor para estruturar os dados, permitindo que seja gerado código nativo de forma automática.
Cache
O Apollo possui seu próprio cache. Todos os dados buscados no servidor são normalizados e armazenados em um cache local. Isso ajuda a manter os dados consistentes e sempre atualizados.
Políticas de busca
Pode-se escolher facilmente entre buscar dados no cache ou acessar o servidor. Dessa forma, você pode evitar solicitações desnecessárias ao backend.
Configurando seu projeto
Para configurar e executar a sua primeira query com o Apollo no seu projeto, vamos precisar concluir as seguintes etapas:
- Instalar o apollo via npm: necessário para que seja possível baixar a estrutura da API e, também, precisaremos do apollo codegen o qual será responsável por gerar código nativo em swift onde estarão todas as estruturas e queries gerados a partir de um schema;
- Baixar o schema disponível a partir do servidor: a partir disso teremos um arquivo schema.json o qual devemos colocar dentro do projeto;
- Criar o arquivo .graphql: nele vamos colocar nossa query de exemplo. Esse arquivo deve também estar dentro no projeto;
- Instalar a dependência do Apollo no nosso projeto: pode ser instalado via CocoaPods, Carthage, Swift Package Manager ou manualmente. Nesse exemplo usaremos CocoaPods.
- Configurar o Apollo Build Phase: executa o apollo codegen em tempo de build para criar o arquivo API.swift, o qual é a estrutura que define as estruturas e queries;
- Rodar o projeto.
Para este exemplo, vamos usar a API pública de filmes da EtMDB (Ethiopian Movie Database). A documentação e o simulador de queries podem ser acessados por aqui.
Vamos precisar instalar a dependência do Apollo.
Neste exemplo usei o CocoaPods e adicionei a linha pod ‘Apollo’ no arquivo de Podfile, após isso abra o arquivo .xcworkspace.
Para darmos início a configuração do projeto, o Apollo iOS precisa de um GraphQL schema para que seja possível definir quais queries e mutations podem ser executadas, além de saber quais os recursos estão disponíveis para o cliente. Um arquivo de schema é no formato JSON e convencionalmente é chamado de schema.json.
Iremos precisar do apollo junto com o apollo codegen. Caso você não tenha o apollo instalado no seu terminal, pode-se utilizar o comando abaixo para instalá-lo através do npm. O atributo -g faz com que o módulo seja instalado e acessível globalmente. Caso não tenha o npm, basta instalá-lo também.
Para realizarmos o download do schema do EtMDB vamos utilizar o comando acima, onde ele vai baixar o respectivo schema disponível aqui.
Convencionalmente, é usado esse formato de endpoint para baixar os schema, ou seja, a URL base mais o /graphql no final. Com o arquivo de schema baixado, você deve colocá-lo dentro do seu projeto.
Neste exemplo, coloquei no path Common/Schema/schema.json.
Com o schema em mãos, podemos criar queries para consumir os dados do EtMDB. É possível executar queries de testes e ver a documentação aqui. No exemplo acima, pegamos todas as notícias dos filmes entre um período de datas.
A partir de nossos testes da API, conseguimos montar nossa query a partir do conceito de query language do GraphQL para que o Apollo possa dinamicamente reconhecer e gerar código nativo que seja possível executar as consultas.
No exemplo acima, criamos um arquivo que convencionalmente a sua extensão é no formato .graphql, no qual será o formato de arquivo onde iremos colocar nossas queries e deverá ser colocado dentro do seu projeto.
Você precisa definir um script de configuração no Build Phases do seu projeto como o exemplo acima. Esse script deve estar acima da seção de Compile Sources.
Ele irá interpretar seu schema e seus arquivos .graphql e, com o apollo codegen, irá gerar um outro arquivo em swift, que no caso será no path API/API.swift, e deixará seu projeto configurado para que possa ser utilizado via código. Agora é necessário fazer um build no projeto para que ele aplique as configurações acima.
Projeto de exemplo
A camada de API vai precisar de uma instância do Apollo Client para que seja possível realizar as consultas e mutações. Para isso, precisamos criar um HTTPNetworkTransport e será nele que vamos fazer algumas pré configurações como, por exemplo, definir a url da API, se você quer usar GET em suas queries (o default utilizado é o POST), implementar seu delegate entre outras configurações. Nesse exemplo vamos definir apenas a url, como no exemplo acima.
No método de consulta vamos usar o fetch passando nossa query a qual foi configurada no arquivo .graphql e, a partir disso, foi gerado automático a classe GetAllNewsQuery e com seus respectivos parâmetros que serão usados na consulta.
No exemplo acima temos um exemplo de resultado, onde podemos mapear e tratar os três tipos de casos. No caso de sucesso temos um exemplo de como acessar os dados das notícias dos filmes.
Para acessarmos os respectivos dados, precisamos ir até o nível dos edges onde encontra o array de node. O padrão de resposta de uma API GraphQL é no formato json também e, para esse caso, segue a estrutura como mostrado acima, ou seja, data -> sua query -> edges -> array de node.
Cache ao lado do cliente
O Apollo iOS permite construir um cache de dados que é mantido e atualizado à medida que novas consultas e mutações são executadas. Sendo assim, a interface do usuário é sempre consistente internamente e pode ser mantida atualizada com o servidor a partir do número mínimo de consultas necessárias.
O cacheamento pode ser feito de duas maneiras, o padrão é via memória RAM o qual é mantida apenas durante a execução ao aplicativo. A outra alternativa é usando o SQLite para armazenar resultados em disco e, para isso, existe a biblioteca ApolloSQLite.
Vale ressaltar que o cacheamento via persistência SQLite tem respostas um pouco mais lenta devido a leitura que precisará ser feita no disco.
O método fetch mostrado acima possui um atributo opcional chamado cachePolicy que permite especificar quando os resultados devem ser buscados no servidor e quando os dados devem ser carregados no cache local. O valor padrão é .returnCacheDataElseFetch, o que significa que os dados serão carregados do cache quando disponíveis ou buscados os dados no servidor, caso contrário. Os outros métodos de cache que existem são:
- fetchIgnoringCacheData: Sempre busca os dados no servidor, mas ainda assim são armazenados os resultados em cache;
- fetchIgnoringCacheCompletely: Sempre busca os dados no servidor e não são armazenados os dados em cache;
- returnCacheDataDontFetch: Retorna os dados do cache e nunca busca no servidor. Retornará um erro se os dados em cache não estiverem disponíveis;
- returnCacheDataAndFetch: Retorna os dados do cache e sempre faz uma busca no servidor para ver se há alguma atualização.
Conclusão
Este é apenas um pequeno exemplo do que o Apollo pode fazer. Vários tipos de queries complexas podem ser feitas também. Checando a documentação do GraphQL na seção de queries podemos ver o poder que temos nas consultas e o Apollo nos ajuda com uma implementação fácil e rápida. É possível também fazer mutações com o Apollo para executar alterações nos dados do servidor.
O projeto Apollo é novo e já têm muitos usuários contribuindo no projeto Open Source. Há muitas coisas por vir e você também pode, é claro, contribuir. Acesse os projetos por aqui.