Gerenciando Estados Visuais no SwiftUI - @State & Binding
-
Garantir que a interface do usuário esteja sempre de acordo com o estado real das coisas. Todas as vezes que houver qualquer alteração em um dado do seu aplicativo, você, como o programador, precisa atualizar todas as interfaces que utilizam esse dado. E aí, pessoal, tudo bem com vocês?
Aqui quem fala é Michel Lopes, sou desenvolvedor iOS, professor de programação, e para quem ainda não me conhece, aqui embaixo tem um link de um vídeo onde você pode me conhecer um pouco melhor. No vídeo de hoje, vamos explorar um assunto fundamental para a evolução de vocês. Ele é considerado um dos pilares de grande parte das coisas que fazemos em SwiftUI. Espero que você, do outro lado, independentemente do seu nível de conhecimento, consiga absorver o máximo possível. O ponto de hoje é @state e @binding no SwiftUI. Nosso desafio será reconstruir parte de uma interface que se encontra nas configurações de tela e brilho do iPhone.
Para ter acesso a essa tela, você vai em "Settings" ou "Ajustes" do seu iPhone e seleciona a opção "Display Brightness" ou "Tela e Brilho", dependendo do idioma do seu dispositivo. Nessa interface, existem alguns detalhes que ainda não mostrei a vocês. Alguns deles serão abordados no vídeo de hoje, e outros teremos que deixar para depois, pois a prioridade é outra. Então vamos nessa. Crie um projeto em branco no SwiftUI. Nosso primeiro objetivo na construção dessa interface serão essas duas linhas aqui. Então, vamos lá, primeiro passo: formulário. Beleza. Agora vou trocar o texto. Vou inserir o segundo texto logo aqui. Como vocês já perceberam, precisamos fazer um stack horizontal para suportar esses elementos aqui. Começando pelo "Options" aqui embaixo, nesse stack vou colocar um "Spacer" e outro texto aqui. Veja como está ficando nossa interface. Agora vou inserir uma section. Lembram das sections? Fazemos isso dentro do formulário.
E vou colocar todos os nossos elementos dentro, as nossas duas linhas. Na nossa interface, não sei se você reparou, mas existe esse elemento aqui. Está vendo? Esse "appearance" e esse "brightness", eles não ficam dentro das linhas. Eles ficam na section. Por isso criei a nossa section. Para que eu possa colocar esse texto dentro, vou até a section, HEADER, excluo esses elementos e coloco um texto aqui dentro. Dê uma olhada agora no nosso projeto. Já apareceu aquele "appearance" ali em cima. Beleza, agora vamos criar o "Toggle" ou "Switch".
No SwiftUI, o "Toggle" se chama "Toggle". Vou colocá-lo aqui. O processo é o mesmo. Abaixo desse texto automático, vou colocar um "Spacer" e o nosso "Toggle". Deu um erro aqui, um pouco diferente do texto. O "Toggle" é um elemento visual, um controle visual, que permite ao usuário do seu aplicativo interagir e modificar dados. Isso significa que esse controle permitirá que dados sejam alterados dentro do seu aplicativo. Ou seja, o usuário poderá ligar ou desligar. Através desse comportamento
Ou seja, o usuário vai lá e ele vai ligar ou desligar. E através desse comportamento, informações vão ser alteradas lá dentro. O Toggle, assim como outros controles que são um pouquinho mais avançados, eles exigem um tratamento um pouquinho especial na hora de você inserir eles dentro de uma interface.
Existem formas de contornar esse problema. Mas de maneira geral, a principal informação que o Xcode tá te pedindo nesse momento é uma maneira de evitar um problema chamado de inconsistência de dados. O SwiftUI é saf, ele já sabe que você tá utilizando um controle visual, capaz de gerar interação com o usuário, e também capaz de gerar o problema de inconsistência de dados lá na frente. Então ele o Xcode já previne você de avançar com esse problema. Ele já começa a te alertar desde agora. Talvez você nunca nem tem ouvido falar desse nome inconsistência de dados, mas eu acho que agora você já percebeu que pode ser uma coisa um pouquinho mais séria, né? Então para que a gente possa avançar nesse vídeo, eu queria garantir que você sabe exatamente do que está tratando, pelo menos, tem uma noção do que esse problema pode causar.
O problema da inconsistência de dados, ele acontece quando a interface, ela não está reproduzindo a situação real da informação. Por exemplo, imagina um jogo de futebol campeonato brasileiro. Primeiro tempo em ser rouca, tava zero a zero. A galera sai de estádio ali, vai na lanchonete, compra uma comida. E quando volta, do nada, o placar reproduz. 7 a zero. Imagina a dor de cabeça. A primeira vista isso pode parecer bem besta, porque na real, ninguém nunca deixaria passar essa situação, né? A galera ia gritar, o juiz ia lá no placar, e arrumar e voltar tudo ao normal. Mas dependendo da situação do cenário, esse estrago ele pode ser grave. Por exemplo, imagina a situação onde um piloto de um avião tá tentando pousar, e aí ele olha no painel, e a informação de altitude daquele painel, ela não está reproduzindo a informação real. Olha a tragédia que pode acontecer nessa situação. Trasendo mais para o nosso universo, a medida que um app cresce, fica muito mais difícil para um programador, garantir que a interface do usuário sempre esteja de acordo com o real estado das coisas. Todas as vezes que houver qualquer alteração, em um único dado do seu aplicativo, você, como o programador, precisa sair correndo e atualizar todas as interfaces que utilizam aquele dado. Por isso, quando estamos criando um app, em algumas situações do SwiftUI, nos obriga a fazer um elo de conexão entre a interface e a informação. O objetivo dele é tentar garantir que nunca ocorra uma inconsistência de dados.
Como eu falei anteriormente, existem formas de você contornar esse problema, mas, de maneira geral, o Xcode está te cobrando um elo de conexão. Entre este controle, que é capaz de gerar um problema de inconsistência de dados, e a informação, o dado onde as coisas serão conectadas.
Entre esse controle, que é capaz de gerar um problema de inconsistência de dados e a informação, o dado onde as coisas serão conectadas. Então, até agora, a gente não tem a informação. A gente só tem o controle visual, que é o Toggle. Antes de qualquer coisa, nós vamos criar uma variável e, ali dentro, nós vamos ter a informação e vai ser usada para esse elo com o Toggle. E, se você não sabe o que é uma variável, já fiz um vídeo que pode te ajudar. O link está aqui em algum lugar nessa tela. Eu vou comentar o nosso Toggle e, aqui em cima do bar, eu vou criar a nossa primeira variável. Beleza, então, a gente já tem o local onde a gente vai guardar essa informação. O objetivo lembra, é conectar o Toggle, que é esse carinho aqui embaixo, com a informação. É esse carinho aqui, que está sendo guardado dentro da nossa variável. Mas ainda está faltando um detalhe. Uma variável comum, ela não é capaz de receber uma conexão com um controle visual. A gente precisa habilitar essa variável para que ela consiga receber esse tipo de conexão.
Uma das maneiras mais comuns de fazer isso e simples é inserindo esse arroba state logo à frente da variável. Quando a gente tem um arroba, seguido de um comando no SwiftWire, isso se chama um wrapper, mas não se estressa, não. Nem se preocupa com isso agora. O importante aqui é que quando inserimos o state na frente da variável, nós estamos jogando a responsabilidade dessa variável para o SwiftWire e a View.
Agora, o SwiftWire vai conseguir alterar os valores dessa variável automaticamente e ele vai conseguir também monitorar os valores dessa variável para você. O SwiftWire vai entender que aquela View, no nosso caso a ContentView, ela tem uma variável que precisa de cuidados.
Mas que tipo de informação a gente coloca em uma variável que está marcada com esse state? E a resposta para essa pergunta é qualquer informação que te ajude a controlar o estado visual da sua interface. Por isso ela tem o nome de state. Por exemplo, você pode usar variáveis do tipo state para dizer se um botão vai estar ativo ou inativo. O botão inativo é um estado, o botão ativo é outro estado. Você pode controlar a posição do scroll, você pode controlar se em algum momento o texto vai ser negrito ou se em algum outro momento o texto vai ser itálico.
Existem inúmeras possibilidades e você usa isso conforme a sua necessidade. Para te ajudar a tentar imaginar, quando uma propriedade recebe esse state na frente, ela fica no agente abusada. Porque a partir de agora, ela nunca mais vai permitir que a View seja livre.
Ela vai começar a obrigar essa View a se adaptar às vontades da propriedade primeiro e só depois exibir as coisas pros outros. Nós chamamos essas propriedades, essas variáveis, de transmissão de informação para a interface de source of truth. E uma tradução direta é como se fosse a fonte da verdade. Mas para te ajudar, tem de imaginar como se fosse o dono da razão.
Sabe aquelas pessoas que sempre têm razão e a gente nem perde tempo discutindo? E a gente acaba cedendo só pra evitar qualquer tipo de estresse. Você pode imaginar o processo dessa mesma maneira. Quando aparece aquele dono da razão, ou seja, esse source of truth, cheio de vontade. A Viu, ela nem perde tempo discutindo. Ela só aceita o que ele tem a dizer pra evitar problemas.Uma das perguntas mais importantes que devemos fazer quando estamos escrevendo uma interface no SwiftUI é de onde virão os dados. A source of truth serve exatamente para nos ajudar a responder essa pergunta. Uma View tem a opção de consumir dados internos, ou seja, dados locais, e nesse caso a gente usa o state, como ela também tem a opção de consumir dados externos, dados que estão vindo de outros lugares. Então não existe uma única forma de transmitir dados para sua interface. Todas essas opções aí possuem características distintas e para que você possa saber qual delas utilizar, depende da sua necessidade. Mas para evitar qualquer distração confundindo a cabeça de vocês, hoje nós vamos explorar apenas o state. Ele é o mais simples de todos e também costuma ser um dos mais utilizados. Então, na prática, sempre que uma propriedade com o state na frente for utilizada dentro de uma View, o SwiftUI vai entender que a exibição dessa View depende daquele valor.
Então a View vai começar a ceder e se adaptar às atualizações da propriedade. Isso quer dizer que sempre, sempre que houver uma alteração na variável, qualquer uma, automaticamente a View vai reconstruir todo o seu conteúdo de acordo com o novo valor. E aí talvez vocês estejam achando agora que esse processo é muito custoso e que pode demorar demais, mas não se esqueçam que o SwiftUI funciona no estilo de programação declarativo. Isso quer dizer que tudo isso que eu falei para vocês é automático e muito otimizado. É muito rápido. E agora que você já entendeu como todo esse processo funciona, você está pronto para fazer uma conexão entre o controle visual pelo Toggle e a nossa informação, que no caso é a variável 'ligado' que está nesse estado. Para fazer essa conexão é muito simples. Eu vou tirar esses comentários. Dentro do parênteses, eu vou escrever isso: on:, o passado, o sifram e o nome da nossa variável. Pronto, de um lado nós temos o controle visual que é o Toggle e agora do outro lado, nós temos a variável com esse state na frente. Essa conexão não tem nome, ela se chama Binding.
No SwiftUI, quando você perceber que um controle visual está recebendo uma variável através desse siframzinho, isso quer dizer que ali está acontecendo um Binding. Ali está acontecendo uma conexão entre o controle da interface e uma informação para que nunca aconteça a inconsistência de dados. E olha só, o Binding, ele não é de uso exclusivo dessas propriedades do tipo state. Lembra daquelas outras opções de source of truth?Se você continuar fazendo isso com uma certa frequência, com o tempo, você vai ganhando mais autonomia. E aí vai chegar aquele momento maravilhoso onde você começa a perceber que você investe muito mais tempo, criando suas próprias coisas, produzindo as suas coisas, do que copiando. Antes de a gente finalizar o vídeo, eu vou dar um tapa nessa interface porque ela está horrível para aí.
Pessoal, só para deixar claro, existem muitas formas de melhorar esse código aqui. Dá para a gente deixar isso aqui liso, liso, liso. Mas vamos lá. Eu criei três constantes e coloquei dentro dessas constantes tudo que é relacionado à seção. E aí a novidade é que na linha 38, da mesma forma que eu estou passando com o nosso header, eu também estou passando esse footer. Eu também dei uma melhorada nos tamanhos, na fonte e nas cores da nossa interface. E por último, inseri essa imagem aqui em cima. Lá na frente, eu vou ensinar para vocês como a gente cria controles personalizados no Switch UI, mas por enquanto, o objetivo também não é esse. Vamos ver como ficou. Vou dar o play. Olha aí a nossa interface. Já está com uma nova cara. Olha o nosso slider funcionando. Isso aqui, vocês viram que é uma imagem. Tá tranquilo.
Depois eu vou mostrar para vocês como a gente customiza controles visualizados no Switch UI. Deixa eu trazer aqui o nosso modelo. Fica perto. Faltou essa parte aqui embaixo, mas também, agora vocês já sabem como faz. Fica o desafio aí para vocês. ... Era isso que eu tinha para falar com vocês hoje. Eu espero que vocês tenham gostado. Pessoal, esse assunto abre a gente para aprender muita coisa legal daqui para frente. E se você estiver gostando deste quadro do início ao fim, onde o objetivo é pegar o conteúdo, destrinchar ao máximo, detalhar o máximo possível, entregar para vocês no idioma Português.
Não esquece de ir ali embaixo, Fala o subscribe no canal, ativa o sininho, porque aí as próximas vezes que eu lançar um novo vídeo, você vai ser notificado. Pessoal, tudo de bom para vocês, um grande abraço, estamos juntos, tchau, tchau!