React Native — Comunicação com módulos nativos (iOS)

Iago Cavalcante
January 12, 2024

Módulos nativos

O post de hoje começa com uma pergunta, por que criar módulos nativos usando o react native ?

Se você trabalha com desenvolvimento mobile, em algum momento você irá esbarrar com alguma lib, algum sdk que só possui versões pra Android ou iOS e você tem o aplicativo já em andamento com React Native.

Dado esse cenário, surge a necessidade de entender, estudar e aprender a criar a comunicação usando React Native, isso é possível e com isso a gente é capaz de extrapolar o comum e passar a desenvolver aplicativos mais poderosos ou até contribuir criando um pacote que não existia para abstrair o SDK/Lib nativas.

Para criar os módulos nativos temos duas opções, criar um pacote NPM/Yarn ou criar o módulo nativo dentro do nosso projeto de aplicativo.

Caso de uso

Nosso caso de uso será o SDK do Zoom.us onde vamos modificar um pacote existente para react native. Com isso vamos criar novos métodos para suprir nossa necessidade. São métodos que existem no SDK, porém não existe no pacote que utilizamos para testar. Logo nosso time percebeu a necessidade de modificar o pacote pra atender nossas necessidades.

Primeiro passo foi estudar o código do pacote e estudar a documentação oficial do React Native especificamente na parte de criação de módulos nativos, inclusive está sendo discutido uma nova arquitetura, chamada TurboModules.

Temos no código-fonte do pacote o seguinte trecho:

Onde na linha um importamos o NativeModules do react-native e é a partir dele que temos acesso aos módulos nativos do iOS e Android, no nosso caso nesse primeiro artigo vamos focar no iOS. O alvo das nossas alterações será o RNZoomUsBridge através dele vamos ter acesso as funções do SDK.

Nosso alvo aqui é usar um SDK já existente e usufruir dele, com isso nosso pacote só será a ponte entre o React Native e o SDK, pra isso precisamos configurar um arquivo que irá dizer onde está o SDK, que no caso do iOS é a configuração do

FRAMEWORK_SEARCH_PATHS.

O nome do arquivo que fica na raiz do pacote tem o mesmo nome do pacote e tem a extensão .podspec.

Podemos ver na imagem acima, na linha vinte e cinco que configuramos o local do ZoomSDK que vai ser instalado no projeto (aplicativo) e não no nosso pacote.

No pacote existem arquivos .h e .m, eles são arquivos responsáveis pela definição do módulo (.h) e o pela implementação do módulo (.m). O que interessa pro nosso caso de uso são o RNZoomUsBridge.h, RNZoomUsBridge.m, RNZoomUsManager.h e RNZoomUsManager.m.

Quando abrimos o primeiro arquivo temos o seguinte:

Ele define que a interface RNZoomUsBridge vai ser um objeto RCTBridgeModule, que é importado diretamente do React.

Com isso podemos ir para implementação dessa interface que fica no arquivo RNZoomUsBridge.m:

No início do módulo temos as importações de outros módulos e ao ir mais para baixo desse módulo temos a implementação usando a assinatura do módulo do react native para ser entendido como um método no Javascript, o que chamamos de ponte.

O React usa o método abaixo para chamar, executar o módulo nativo, com isso temos uma implementação usando Promise, mas poderia ser outro tipo de implementação.

Na linha cento e trinta e três dizemos o nome do método e o tipo de retorno, que no nosso caso é uma Promise, que pode dar certo ou errado. Se der certo a execução do método nativo não vamos retornar nada e se der errado mostramos uma mensagem de erro.

Podemos ver na linha cento e quarenta e um que chamamos o Manager e ele é responsável por executar nosso método hideMeeting.

Agora vamos olhar como está definido e implementado esse método no Manager.

Como vimos anteriormente, os arquivos .h são definições das interfaces. Nela vamos definir quais métodos temos que implementar e utilizar.

Na nossa implementação do manager temos o seguinte:

Podemos ver que aqui importamos o MobileRTC, esse arquivo é importado diretamente do SDK do Zoom.us e com ele temos acesso a vários métodos, interface, enums e tudo mais.

O que precisávamos pro nosso caso de uso era executar a ação de minimizar a tela de reunião do Zoom.us para executar outra ação. Lendo o código fonte do SDK chegamos ao método showMinimizeMeetingFromZoomUIMeeting e para implementar isso escrevemos o seguinte trecho:

Nesse método definimos ele como assíncrono e definimos quando ele irá parar a execução (definir como completa) usando completionBlock. Foi instanciado o objeto ms que é referente ao meetingService que é a reunião em execução e nele executamos a ação para minimizar a janela com [ms showMinimizeMeetingFromZoomUIMeeting] e para facilitar a leitura, deixamos alguns logs para identificar se tudo está ocorrendo como o esperado.

Conclusão

Com isso vimos como usufruir de módulos nativos usando objective-C e SDK nativo. Claro que isso exige um mínimo de conhecimento das linguagens nativas de cada plataforma e pode parecer assustador no início. Esse foi um caso real que foi necessário ser feito para atingir os objetivos da nossa aplicação e a lib modificada pode ser encontrada nesse repositório.

Para quem vem da web ou já tem familiaridade com React Native, vale a pena entender como a ponte (bridge) funciona e como a gente pode desenvolver apps melhores usufruindo desse poder.

Por hoje é só, até mais pessoal.