Qual é a diferença entre -viewWillAppear: e -viewDidAppear :?

131

Qual é a diferença entre -[UIViewController viewWillAppear:]e -[UIViewController viewDidAppear:]?

PJR
fonte
1
graças BoltClock, mas por favor me dê exemplo de ambos, se possível ..
PJR
3
@BoltClock seria bom se isso fosse verdade. Eu estou supondo que as 15 pessoas que upvoted ler o nome do método, mas nunca realmente mediu ... Vim aqui do Google, porque essa não é a diferença entre eles
Adam
1
Especificamente: parentView.viewDidAppear é chamado MUITO TEMPO antes que a Apple realmente mostre parentView ... A Apple primeiro (atomicamente) pinta todas as subvisões ... e se você tiver muitas subvisões ou complexas, então "viewDidAppear" pode ser chamado de dezenas ou centenas de milissegundos muito cedo :(.
Adam

Respostas:

292

Em geral, é isso que eu faço:

1) ViewDidLoad - Sempre que adiciono controles a uma exibição que deve aparecer junto com a exibição, eu o coloco no método ViewDidLoad. Basicamente, esse método é chamado sempre que a exibição foi carregada na memória. Por exemplo, se minha visualização for um formulário com três marcadores, eu os adicionaria aqui; a visão nunca existirá sem essas formas.

2) ViewWillAppear : Eu uso o ViewWillAppear normalmente apenas para atualizar os dados no formulário. Portanto, para o exemplo acima, eu usaria isso para realmente carregar os dados do meu domínio no formulário. A criação de UIViews é bastante cara e você deve evitar o máximo possível fazer isso no método ViewWillAppear, porque quando isso é chamado, significa que o iPhone já está pronto para mostrar o UIView ao usuário e qualquer coisa pesada que você fizer aqui afetará o desempenho de maneira muito visível (como atrasos nas animações etc.).

3) ViewDidAppear : Finalmente, eu uso o ViewDidAppear para iniciar novos threads para coisas que levariam muito tempo para serem executadas, como, por exemplo, fazer uma chamada de serviço da web para obter dados extras para o formulário acima. já existe e está sendo exibido ao usuário, você pode mostrar uma boa mensagem "Aguardando" para o usuário enquanto obtém os dados.

Chetan Bhalara
fonte
4
Desculpe, mas o que você quer dizer com "carregar os dados do meu domínio no formulário" em viewWillAppear? Você quer dizer fazer o download pela rede? Mas você também sugere o download de material viewDidAppear?
precisa saber é o seguinte
1
@ Philip007 Acho que o Stack está se referindo a esse tipo de domínio: en.wikipedia.org/wiki/Domain-specific_modeling . Os dados são carregados dos seus modelos ou similares.
dentarg
2
Esta resposta deve estar na documentação. Foi realmente útil para esclarecer a diferença entre os três métodos. Obrigado!
GangstaGraham
1
+1 eu estava tendo um pouco de confusão compreender a diferença entre estes três, mas você apenas limpou-se mais do que perfeitamente @ChetanBhalara
Chisx
@ChetanBhalara mas se você colocar o trabalho longo em ViewDidAppearque você vai facilmente fazer confundir usuário sobre UI :)
HQT
46

viewDidLoad === >>> Coloque seu código de inicialização aqui. Não coloque dados dinâmicos que possam mudar durante o ciclo de vida da exibição. Portanto, se você está obtendo dados dos dados principais, não deseja fazê-lo aqui, se isso puder mudar durante a vida útil da exibição. Por exemplo: digamos que você tenha um controlador de tabulação. Você alterna da tab1 para a tab2 e altera algo no modelo da tab2. Se você voltar à tab1 e ​​o código do seu modelo tiver sido feito em viewDidLoad, isso não será atualizado (supondo que você não esteja usando o KVO ou NSFetchedResultsController, etc.).

viewWillAppear === >>> Isso é chamado toda vez que a exibição está prestes a aparecer, independentemente de a exibição já estar na memória. Coloque seu código dinâmico aqui, como a lógica do modelo.

viewDidAppear === >>> Coloque aqui operações caras que você só quer fazer se tiver certeza de que a exibição está na tela, como chamadas de rede.

Aviso: se o aplicativo estiver em segundo plano e retornar ao primeiro plano, você precisará lidar com isso usando o NSNotificationCenter. Eu escrevi o código para isso nos comentários abaixo. Você pode pensar que o viewWillAppear / viewDidAppear será acionado. Coloque um ponto de interrupção lá e teste-o. Não dispara. Portanto, se algo mudou para o seu aplicativo enquanto estava em segundo plano, você precisará atualizá-lo usando as notificações.

smileBot
fonte
1
O ViewWill ou o ViewDid é executado cada vez que você minimiza o aplicativo?
Jeef 02/04/19
2
@ Jeef Esta é uma excelente pergunta. Nenhum deles é executado, a menos que o aplicativo seja eliminado pelo sistema ou pelo usuário enquanto estiver em segundo plano. O que você precisa fazer para ser notificado quando o aplicativo não é minimizado é usar o NSNotificationCenter e o addObserver para o nome UIApplicationWillEnterForegroundNotification. O seletor deve ser applicationWillEnterForeground: possui um paramater NSNotification. Coloque seu código nesse método para recarregar dados, etc. O que você pode fazer é criar um método de recarregamento que você chama de formar esse método e também viewDidAppear se eles precisarem ser os mesmos.
smileBot
2
@Jeef algo como isto: - (void) viewDidLoad {[[NSNotificationCenter defaultCenter] addObserver: auto-seletor: @selector (applicationWillEnterForeground :) nome: objeto UIApplicationWillEnterForegroundNotification: nil]; } - (void) applicationWillEnterForeground: (NSNotification *) de notificação {// responder aqui com o que}
smileBot
12

O viewWillAppearmétodo é chamado antes de carregar a visualização real.

O viewDidAppearmétodo é chamado quando a exibição já está carregada e você deseja mostrar algo.

puneet kathuria
fonte
9

viewWillAppear:
■ Chamado antes que a visualização seja adicionada à hierarquia de visualizações da janela
■ Chamado antes de [vc.view layoutSubviews] (se necessário)
viewDidAppear :
■ Chamado após a visualização ser adicionada à hierarquia da visualização
■ Chamado após [vc.view layoutSubviews] (se necessário)

andyqee
fonte
7

Algumas observações:

  • O viewDidLoadmétodo é chamado quando a exibição é instanciada pela primeira vez. IBOutletas referências são conectadas no momento em que isso foi chamado, mas não antes. O ponto framede vista pode não ser estabelecido no momento em que isso foi chamado. Este é um ótimo local para adicionar / configurar subvisões e suas restrições associadas. Mas se você estiver fazendo uma configuração manual de framevalores com base nas dimensões da vista principal, a configuração desses quadros deve ser adiada até viewWillAppearou viewDidLayoutSubviews.

  • O viewWillAppearmétodo é chamado quando a apresentação da exibição na hierarquia da exibição está prestes a começar. Notavelmente, isso é chamado no início da animação (se houver) da apresentação da exibição. Seu companheiro, viewWillDisappearobviamente , é chamado quando a transição para longe dessa visão começa.

  • O viewDidAppearmétodo é chamado quando a apresentação da exibição é concluída, principalmente quando toda e qualquer animação associada termina. Seu companheiro, viewDidDisappearobviamente , é chamado quando a transição para longe dessa visão é feita.

Duas advertências importantes:

  • viewDidLoadé chamado uma vez e apenas uma vez, quando a exibição é instanciada pela primeira vez. Por outro lado, viewWillAppeare viewDidAppearserá chamado não apenas quando a exibição for apresentada pela primeira vez, mas a cada vez subsequente, a mesma exibição em questão será reapresentada. Por exemplo, quando você apresentar uma exibição pela primeira vez, todos esses três métodos serão chamados. Se a vista em questão, posteriormente, apresenta outro ponto de vista que é posteriormente demitido, o viewWillAppeare viewDidAppeargeralmente será chamado novamente quando a vista em questão é adicionado e animado de volta para a hierarquia de vista, mas viewDidLoadnão vai. viewDidLoadé chamado somente quando essa instância específica é criada pela primeira vez.

    Portanto, se você quiser fazer algo toda vez que uma exibição reaparecer (por exemplo, você a dispensa ou volta a exibir), faça-a em viewWillAppearou viewDidAppear. Se você deseja que isso aconteça somente quando a visualização for instanciada pela primeira vez, faça isso viewDidLoad.

  • A chamada de viewWillAppearnão garante que a transição para essa exibição seja concluída. Notavelmente, se você estiver usando uma transição interativa que é direcionada pela entrada do usuário em tempo real, mas essa transição interativa pode ser cancelada. Ou seja, apenas porque viewWillAppearé chamado, não significa que viewDidAppearserá chamado. Geralmente é, mas se o gesto interativo for cancelado, não será (porque a transição nunca terminou).

    Na WWDC 2013, no contexto de transições interativas, um apresentador brincou dizendo que deveria renomear viewWillAppearpara " viewMightAppear, ou viewWillProbablyAppear, ou iReallyWishThisViewWouldAppear".

    Um exemplo de um gesto interativo embutido é quando você usa um UINavigationControllere você "desliza da borda esquerda" para iniciar um pop na exibição. O viewWillAppearserá chamado para a vista à qual estão surgindo, mas se você cancelar que "swipe da borda esquerda" para voltar para o ponto de vista do qual você iniciou este gesto pop, o pop é cancelada e o viewDidAppearpara a vista você começou a voltar para nunca será chamado.

    O efeito líquido disso é que você deve tomar cuidado para não escrever um código que pressupõe que todas as chamadas para viewWillAppearserão seguidas eventualmente por uma chamada para viewDidAppear. Se a transição for cancelada, não será esse o caso.

Roubar
fonte
5

viewwillappear chamará antes de carregar a visualização, para que você possa executar determinadas tarefas antes de carregar essa visualização, e viewdidappear chamará após carregar a visualização, para que a tarefa de postagem seja executada nesse método

dks1725
fonte
4

Diferença entre "will" e "did" ... Como o nome sugere, o viewWillAppear é chamado antes da exibição estar prestes a aparecer e o viewDidAppear é chamado quando o view apareceu.

Mahesh
fonte
veja a resposta aceita mano, que contém mais de 70 votos positivos. :)
PJR
4

1) ViewWillAppear : a exibição carregada na memória, chamada uma vez no controlador de exibição e tinha seu quadro, mas ainda não apareceu para o usuário

2) ViewDidAppear : o controlador foi adicionado à hierarquia da visualização, para que você pudesse apresentar ao próximo controlador, também, a visualização fez o layout das subvisões

Abuzeid Ibrahim
fonte
3

O primeiro acontece antes que a visualização apareça e o segundo acontece depois.

Marc Abramowitz
fonte
3

Resumindo:

-viewWillAppear -> atualizar dados (recarregar dados de uma visualização de tabela)

-viewDidAppear -> operações caras (chamada da API com um bom progresso!)

Nahuel Roldan
fonte
1

Como o nome sugere, viewWillAppearé chamado antes da exibição estar prestes a aparecer e viewDidAppearé chamado quando a exibição apareceu.

visakh7
fonte
0

Caso de uso , ou seja, quando devo usar qual?

viewDidLoad - quando etiquetas, botões (ou seja, controles / sub-visualizações) estão conectados ao arquivo de interface do View e se você deseja carregar todos esses itens ao mesmo tempo que o ViewController, e se você deseja carregá-lo na memória uma vez e feito com isso

viewWillAppear- digamos, você deseja alterar a cor de fundo da exibição sempre que o controlador de exibição aparecer na tela. Ou, de forma mais realista, se você quiser a cor de fundo do DarkMode no período noturno do dia e a cor clara da exibição de plano de fundo durante o dia, vá para este código emviewWillAppear

Outro bom caso de uso aqui https://stackoverflow.com/a/39395865/5438240

Observe também que, se você estiver usando uma pilha de Navegação ( UINavigationController), o viewController que está prestes a ser exibido terá a viewWillDisappear()chamada e o ViewController que será o próximo no topo da pilha terá viewWillAppear()chamado

Naishta
fonte