Aplicativo para Apple Watch com SwiftUI

Eduardo Lombardi
4 min readApr 6, 2020

Aproveitando a quarentena, peguei parte do meu tempo livre pra estudar mais a fundo como funciona o SwiftUI e o desenvolvimento de aplicativos para Apple Watch. Vou postar o link do app pra vocês darem uma olhada no final do artigo. Recentemente a Apple lançou os chamados "Independent Watch Apps"; aplicativos independentes que funcionam apenas no Watch sem precisar de uma versão no iPhone.

Para criar o projeto, precisamos escolher watchOS no menu de projetos e a opção WatchApp.

Tela do Xcode para criação do projeto

Ao clicar em próximo, devemos escolher a opção swiftUI como user Interface

Ao criar o projeto o Xcode vai criar uma controller meio diferente do que estamos acostumados:

Ela herda de WKHostingController e tem uma propriedade body que herda de ContentView. ContentView é uma view customizada que vamos ver logo abaixo.

Vamos destrinchar este trecho de código. As views em swiftUI são criadas como structs, ou seja podem ser utilizadas como constantes ou ainda ter suas variáveis internas alteradas, mas não sua instância.

Na linha 2, nossa Struct herda de View, um tipo do swiftUI que representa uma view. Para que tudo isso funcione, precisamos implementar o protocolo. Ele consiste de uma var body, que é do tipo some View. Esse some aí diz que o retorno do corpo do body é opaco. ( Para entender melhor o some, veja este link https://medium.com/@PhiJay/whats-this-some-in-swiftui-34e2c126d4c4)

Dentro do body, temos no caso somente uma view Text, mas podemos construir layouts mais complexos. São várias views diferentes que podem ser combinadas para produzir layouts de maneira mais rica. A outra struct que temos no arquivo é uma que herda de PreviewProvider e está ali apenas para auxiliar o Xcode 11 (no macOS catalina) a realizar as livePreviews do código para que você não precise compilar o app para ver o resultado das alterações.

Uma das views que tenho no app que construi. Perceba que temos elementos de agrupamento como VStack, que permite o alinhamento vertical dos itens, uma ScrollView para que haja scroll na tela e também AnotherCustomView que é uma outra view customizada criada com ainda mais alguns elementos de interface para evitar poluir o código. É tudo muito tranquilo, o Xcode ajuda bastante e a documentação é extensa. Para botões por exemplo, vemos que temos uma closure de ação seguida de uma closure de aparência. Só um detalhe: como body requer algo do tipo opaco some View, você não consegue fazer estruturas com ifs retornandos tipos diferentes (Text e Button), por exemplo, o compilador reclama.

Nem tudo está no código. Ao criar um app para apple watch somos forçados a utilizar um velho conhecido nosso, o StoryBoard, mesmo utilizando swiftUI.

Imagem de um arquivo storyboard com duas HostingControllers

Mas calma que não temos muitas coisas a fazer nele. Não sei se perceberam uma coisa, mas não colocamos outlets no código 🤔. E não precisamos deles ! 1No caso do app que eu fiz, eu apenas criei mais uma Hosting Controller e arrastei uma segue de uma para a outra, clicando em nextPage. Desse modo, a aplicação fica com aquelas bolinhas do pageControl embaixo, e a navegação entre as controllers é automágica. Não se esqueça de associar cada uma das hosting controllers com sua respectiva classe ou o app vai crashar.

Layout definido, hora de trabalhar com o que chamo de back do front, ou as camadas de dados e networking do frontEnd.

Mesmo código anteriormente mostrado, notaram que existe um tal de @state e um tal de $numbers ali? o @state serve para definir variáveis cuja alteração será refletida imediatamente nas views. Como estou utilizando ela dentro de uma customView, preciso passar com $ atrás, e lá na custom view preciso defini-la como

@Binding var numbers:[Int]

Para que as alterações sejam refletidas e o layout fique amarrado. Quando eu atualizar meu array de Numbers, minhas views vão se atualizar automágicamente.

Para o download das informações externas podemos utilizar o URLSession normalmente e se precisarem de ajuda, consultem este artigo aqui que explica melhor como isto funciona : https://medium.com/@calvinw/using-urlsession-to-retrieve-json-in-swift-1-getting-started-d929f3a49c67

Para a transmissão dos dados vamos utilizar o conceito de programação reativa novamente, ou seja, fico escutando: quando os dados forem atualizados pego as novas informações e sigo meus fluxos. A classe de download herda de ObservableObject. Alguém está de olho por alterações…🧐. Temos um objeto (que é o modelo do nosso JSON) e ele tem um @Published, que faz com que ele anuncie suas mudanças. Por padrão o swiftUI vai re-invocar as propriedades body que estejam utilizando os valores marcados como @Published após a alteração dos mesmos. Nossa content view permanece a mesma, só que agora temos um var @observedObject que permite escutar as mudanças propagadas pelos objetos marcados com published externos.

São vários conceitos, mas tudo fica mais fácil pela prática. Tente realizar um app para watch você mesmo usando swiftUI. O app que desenvolvi e me referi no texto é esse aqui: http://bit.ly/MegaWatchApp (PS: quer um código gratuito para baixar? RFT96PWF77Y7 basta resgatar este código na app store. Valeu pessoal, até!

--

--