Estou começando a mergulhar no desenvolvimento do iOS e uma das primeiras coisas que tive que fazer foi implementar um controlador de visualização de contêiner personalizado - vamos chamá-lo SideBarViewController
- que troca qual dos vários controladores de visualização filho possíveis mostra, quase exatamente como um Tab Bar Controller padrão . (É basicamente um Controlador de barra de guias, mas com um menu lateral que pode ser ocultado em vez de uma barra de guias.)
De acordo com as instruções na documentação da Apple, eu chamo addChildViewController
sempre que adiciono um ViewController filho ao meu contêiner. Meu código para trocar o controlador de visualização filho atual mostrado pelo SideBarViewController
parece com este:
- (void)showViewController:(UIViewController *)newViewController {
UIViewController* oldViewController = [self.childViewControllers
objectAtIndex:0];
[oldViewController removeFromParentViewController];
[oldViewController.view removeFromSuperview];
newViewController.view.frame = CGRectMake(
0, 0, self.view.frame.size.width, self.view.frame.size.height
);
[self addChildViewController: newViewController];
[self.view addSubview: newViewController.view];
}
Então comecei a tentar descobrir o que addChildViewController
significa aqui, e percebi que não tenho ideia. Além de colar o novo ViewController
no .childViewControllers
array, parece não ter efeito em nada. Ações e saídas da visão do controlador filho para o controlador filho que eu configurei no storyboard ainda funcionam bem, mesmo se eu nunca ligar addChildViewController
, e não posso imaginar o que mais isso poderia afetar.
Na verdade, se eu reescrever meu código para não chamar addChildViewController
e ficar assim ...
- (void)showViewController:(UIViewController *)newViewController {
// Get the current child from a member variable of `SideBarViewController`
UIViewController* oldViewController = currentChildViewController;
[oldViewController.view removeFromSuperview];
newViewController.view.frame = CGRectMake(
0, 0, self.view.frame.size.width, self.view.frame.size.height
);
[self.view addSubview: newViewController.view];
currentChildViewController = newViewController;
}
... então meu aplicativo ainda funciona perfeitamente, pelo que posso dizer!
A documentação da Apple não esclarece muito o que addChildViewController
significa, ou por que devemos chamá-lo. Toda a extensão da descrição relevante do que o método faz ou por que ele deve ser usado em sua seção na UIViewController
Referência da Classe é, no momento:
Adiciona o controlador de visualização fornecido como filho. ... Este método destina-se apenas a ser chamado por uma implementação de um controlador de visualização de contêiner personalizado. Se você substituir esse método, deverá chamar super em sua implementação.
Há também este parágrafo anterior na mesma página:
Seu controlador de visualização de contêiner deve associar um controlador de visualização filho a si mesmo antes de adicionar a visualização raiz do filho à hierarquia de visualização. Isso permite que o iOS roteie eventos de maneira adequada para os controladores de visualização filho e as visualizações que esses controladores gerenciam. Da mesma forma, depois de remover a visão raiz de um filho de sua hierarquia de visão, ele deve desconectar esse controlador de visão filho de si mesmo. Para fazer ou quebrar essas associações, seu contêiner chama métodos específicos definidos pela classe base. Esses métodos não devem ser chamados por clientes de sua classe de contêiner; eles devem ser usados apenas pela implementação do seu contêiner para fornecer o comportamento de contenção esperado.
Aqui estão os métodos essenciais que você pode precisar chamar:
addChildViewController:
removeFromParentViewController
willMoveToParentViewController:
didMoveToParentViewController:
mas não oferece nenhuma pista sobre quais são os 'eventos' ou 'comportamento de contenção esperado' de que está falando, ou por que (ou mesmo quando) chamar esses métodos é 'essencial'.
Todos os exemplos de controladores de visualização de contêiner personalizados na seção "Controladores de visualização de contêiner personalizados" da documentação da Apple chamam esse método, então presumo que ele atenda a algum propósito importante além de apenas colocar o ViewController filho em um array, mas não consigo imaginar descobrir qual é esse propósito. O que esse método faz e por que devo chamá-lo?
fonte
Respostas:
Eu também estava me perguntando sobre essa questão. Eu assisti Sessão 102 dos WWDC 2011 vídeos e Mr. View Controller, Bruce D. Nilo , disse o seguinte:
Portanto, parece que a chamada para
addChildViewController:
faz muito pouco. Os efeitos colaterais da ligação são a parte importante. Eles vêm de relacionamentosparentViewController
echildViewControllers
. Aqui estão alguns dos efeitos colaterais que conheço:transitionFromViewController:toViewController:…
onde ambos os VCs precisam ter o mesmo painavigationController
,tabBarController
, etc propriedadesfonte
Acho que um exemplo vale mais que mil palavras.
Eu estava trabalhando em um aplicativo de biblioteca e queria mostrar uma bela visualização do bloco de notas que aparece quando o usuário deseja adicionar uma nota.
Depois de tentar algumas soluções, acabei inventando minha própria solução customizada para mostrar o bloco de notas. Portanto, quando desejo mostrar o bloco de notas, crio uma nova instância de
NotepadViewController
e adiciono sua visualização raiz como uma subvisualização à visualização principal. Por enquanto, tudo bem.Então percebi que a imagem do bloco de notas está parcialmente oculta sob o teclado no modo paisagem.
Então, eu queria mudar a imagem do bloco de notas e deslocá-la para cima. E para isso, escrevi o código adequado no
willAnimateRotationToInterfaceOrientation:duration:
método, mas quando executei o aplicativo nada aconteceu! E após a depuração, percebi que nenhum dosUIViewController
métodos de rotação de é realmente chamadoNotepadViewController
. Apenas esses métodos no controlador de visualização principal estão sendo chamados.Para resolver isso, precisei chamar todos os métodos
NotepadViewController
manualmente quando eles são chamados no controlador de visualização principal. Isso logo complicará as coisas e criará uma dependência extra entre componentes não relacionados no aplicativo.Isso foi no passado, antes de o conceito de controladores de visualizações filho ser introduzido. Mas agora, você só precisa
addChildViewController
acessar o controlador de visualização principal e tudo funcionará como esperado, sem nenhum trabalho manual.Editar: Existem duas categorias de eventos que são encaminhados para controladores de visualização filho:
1- Métodos de aparência:
2- Métodos de rotação:
Você também pode controlar quais categorias de eventos deseja que sejam encaminhadas automaticamente, substituindo
shouldAutomaticallyForwardRotationMethods
eshouldAutomaticallyForwardAppearanceMethods
.fonte
addChildViewController
para o controlador pai.-[UIViewController addChildViewController:]
apenas adiciona o controlador de visualização passado em uma matriz de viewControllers que um viewController (o pai) deseja manter a referência. Na verdade, você deve adicionar as visualizações do viewController na tela, adicionando-as como subvisualizações de outra visualização (por exemplo, a visualização do parentViewController). Também existe um objeto de conveniência no Interface Builder para usar childrenViewControllers em Storyboards.Anteriormente, para manter a referência de outros viewControllers dos quais você usava as visualizações, era necessário manter a referência manual deles em @properties. Ter uma propriedade integrada como
childViewControllers
e conseqüentementeparentViewController
é uma maneira conveniente de gerenciar tais interações e construir viewControllers compostos como o UISplitViewController que você encontra em aplicativos para iPad.Além disso, childrenViewControllers também recebem automaticamente todos os eventos do sistema que o pai recebe: -viewWillAppear, -viewWillDisappear, etc. Anteriormente, você deveria ter chamado esses métodos manualmente em seus "childrenViewControllers".
É isso aí.
fonte
iOS "system events"
não vomita muito; não parece ser um termo que a Apple usa?