Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Swift não realiza alterações na UI após a execução da linha com Debug

Após a aula onde aprendemos a colocar um timer na aplicação, fui buscar na web outras formas que poderia ser feito. Encontrei que o comando "sleep()" também é utilizado para pausar aplicações, porém de uma forma diferente. Para experimentar esse comando, troquei o "Timer.scheduledTimer" pelo "sleep(5)". A princípio a aplicação foi pausada pelos 5 segundos configurados, entretanto durante a pausa percebi que a cor do botão não era alterada.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Conforme imagem acima, seguindo a ordem do código deveria ocorrer nesta ordem: verifica a resposta -> muda o backgroundcolor do botão -> espera 5 segundos -> chama a função configurarQuestao(). Entretanto durante a espera de 5 segundos o botão permanecia com a cor sem alterações, mas a alteração da cor vem antes da espera. Fazendo um debug do código, vi que mesmo após ser executada a linha de comando que altera a cor do botão, no simulador a cor não era alterada.

Insira aqui a descrição dessa imagem para ajudar na acessibilidade

Minha dúvida é: Por que a execução do código não está seguindo a sequencia escrita mesmo que no debug ele siga a sequencia?

O escrito é: muda a cor -> espera -> chama a função configurarQuestao() Debug: muda a cor -> espera -> chama a função configurarQuestao() O que mostra no simulador: espera -> muda a cor -> chama a função configurarQuestao() ...... (neste caso como o timer não está entre a mudança de cor e a chamada da outra função, a mudança de cor não é visível ao usuário, ou seja, o timer não cumpre sua função).

Outro exemplo desse "problema" é quando executo um debug na func configurarQuestao(). Teoricamente, a cada alteração de cor e título percorridos, deveria alterar também na UI do simulador. EX: executa a linha que altera a cor e imediatamente a cor no simulador é alterada. Executa a linha que altera o título, imediatamente no simulador o título é alterado. Porém ocorre que somente após a conclusão da func as alterações são apresentadas no simulador (todas de uma única vez).

2 respostas
solução!

Olá Renan Novaes, tudo bem?

O comportamento que você está observando ocorre devido à forma como o código é executado em uma thread única e como o mecanismo de atualização da UI funciona no iOS. Vou explicar isso em detalhes e, em seguida, sugerir como corrigir a situação.

  1. Thread Principal e Interface do Usuário: No iOS, a UI é manipulada na chamada "thread principal" (main thread). Qualquer tentativa de atualizar a UI a partir de uma thread diferente pode causar problemas, incluindo a não exibição das atualizações na interface do usuário.

  2. Timer vs. sleep(): A diferença fundamental entre o Timer.scheduledTimer e sleep() é como eles tratam o fluxo de execução:

    • Timer.scheduledTimer cria um temporizador que opera de forma assíncrona, permitindo que a interface do usuário continue a responder durante a contagem regressiva.
    • sleep(), por outro lado, interrompe a execução da thread atual, incluindo a thread principal, o que pode congelar a interface do usuário durante o período de espera.
  3. Debug vs. Execução Normal: Quando você executa um aplicativo no modo de depuração (debug), o comportamento pode parecer diferente da execução normal. Isso ocorre porque o debug pode pausar a execução em pontos específicos (breakpoints), permitindo que você inspecione variáveis e execute ações passo a passo. No entanto, o modo de depuração não reflete necessariamente o comportamento real do aplicativo em execução normal.

Agora, vou abordar suas dúvidas específicas:

Dúvida 1: Ordem de Execução e Mudança de Cor: No código que utiliza sleep(5), a execução fica suspensa por 5 segundos, mas isso ocorre na thread principal, o que impede que as atualizações da UI, como a mudança de cor do botão, sejam renderizadas até que a thread seja liberada. Portanto, a sequência que você espera não é seguida.

Solução: Para manter a UI responsiva durante a espera, use Timer.scheduledTimer ou a função DispatchQueue.main.asyncAfter. Assim, a interface do usuário continuará a ser atualizada.

Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { _ in
    // Aqui, coloque o código para mudar a cor do botão e chamar configurarQuestao()
}

Dúvida 2: Alterações na UI após a Função configurarQuestao(): Quando você observa que as alterações na UI não são exibidas imediatamente, isso ocorre porque as atualizações na UI devem ser realizadas na thread principal, e a função configurarQuestao() está sendo chamada em segundo plano. Portanto, todas as atualizações da UI dentro dessa função são acumuladas e aplicadas juntas quando a função é concluída.

Solução: Certifique-se de que todas as atualizações da UI, como a alteração de cores e títulos, sejam feitas na thread principal. Use a seguinte estrutura para garantir isso:

DispatchQueue.main.async {
    // Coloque aqui o código para alterar a UI (cores, títulos, etc.)
}

Desta forma, as atualizações da UI serão refletidas imediatamente.

Em resumo, é importante entender como a thread principal e a atualização da UI funcionam no iOS. Evite o uso de sleep() para pausar a execução do aplicativo, pois isso pode bloquear a interface do usuário. Use Timer ou DispatchQueue para realizar tarefas assíncronas, mantendo a responsividade da UI. Além disso, certifique-se de atualizar a UI na thread principal para que as alterações sejam visíveis imediatamente.

Baita explicação!! Muito obrigado mesmo!!!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software