Verificando um UIViewController está prestes a começar estalado a partir de uma pilha de navegação?
-
22-07-2019 - |
Pergunta
Eu preciso saber quando o meu controlador de vista está prestes a ser estalado a partir de uma pilha de nav para que eu possa executar uma ação.
Eu não posso usar -viewWillDisappear, porque que é chamada quando o controlador de vista é movido fora da tela por qualquer motivo (como um novo controlador de vista sendo empurrado em cima).
I especificamente precisa saber quando o controlador está prestes a ser exibido em si.
Todas as idéias seria fantástico, obrigado antecipadamente.
Solução
Eu não acho que existe uma mensagem explícita para isso, mas você poderia subclasse o UINavigationController e substituição -. PopViewControllerAnimated (embora eu não tentei isso antes de eu)
Como alternativa, se não há outras referências para o controlador de vista, você poderia adicionar à sua -? Dealloc
Outras dicas
Substitua o método viewWillDisappear
no VC apresentado, em seguida, verifique a bandeira isMovingFromParentViewController
dentro do override e fazer lógica específica. No meu caso eu estou escondendo a barra de ferramentas controladores de navegação. Ainda requer que o apresentado VC entender que ele foi empurrado embora assim não perfeito.
Tente substituir willMoveToParentViewController:
(em vez de viewWillDisappear:
) na sua subclasse personalizada de UIViewController
.
Chamado pouco antes do controlador de vista é adicionado ou removido de um controlador de vista recipiente.
- (void)willMoveToParentViewController:(UIViewController *)parent
{
[super willMoveToParentViewController:parent];
if (!parent) {
// `self` is about to get popped.
}
}
Felizmente, no momento em que o método viewWillDisappear é chamado, o viewController já foi removido da pilha, por isso sabemos o viewController está aparecendo porque ele não está mais no self.navigationController.viewControllers <é / p>
Swift 4
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let nav = self.navigationController {
let isPopping = !nav.viewControllers.contains(self)
if isPopping {
// popping off nav
} else {
// on nav, not popping off (pushing past, being presented over, etc.)
}
} else {
// not on nav at all
}
}
Código Original
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
if ((self.navigationController) &&
(![self.navigationController.viewControllers containsObject:self])) {
NSLog(@"I've been popped!");
}
}
Esse é um trabalho para mim.
- (void)viewDidDisappear:(BOOL)animated
{
if (self.parentViewController == nil) {
NSLog(@"viewDidDisappear doesn't have parent so it's been popped");
//release stuff here
} else {
NSLog(@"PersonViewController view just hidden");
}
}
Você pode pegá-lo aqui.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
if (viewController == YourAboutToAppearController) {
// do something
}
}
Isto irá disparar um pouco antes da exibição do novo View. Ninguém ainda se movia. Eu uso o tempo todo para fazer mágica na frente do NavigationController asinino. Você pode definir títulos e títulos de botão e fazer o que lá.
Eu tenho o mesmo problema. Eu tentei com viewDisDisappear, mas eu não tenho a função de obter chamado :( (não sei porquê, talvez porque toda a minha VC é UITableViewController).
A sugestão de Alex funciona bem, mas ele falhar se o controlador de navegação é exibido sob a guia Mais. Neste caso, todos os VCs de seus controladores nav têm a navigationController como UIMoreNavigationController, não o controlador de navegação de ter uma subclasse, então você não será notificado pela nav quando um VC está prestes a estourou.
Finalmente, eu resolvi o problema com uma categoria de UINavigationController, apenas reescrever - (UIViewController *) popViewControllerAnimated: (BOOL) animado
- (UIViewController *)popViewControllerAnimated:(BOOL)animated{
NSLog(@"UINavigationController(Magic)");
UIViewController *vc = self.topViewController;
if ([vc respondsToSelector:@selector(viewControllerWillBePopped)]) {
[vc performSelector:@selector(viewControllerWillBePopped)];
}
NSArray *vcs = self.viewControllers;
UIViewController *vcc = [vcs objectAtIndex:[vcs count] - 2];
[self popToViewController:vcc animated:YES];
return vcc;}
Ele funciona bem para mim: D
Eu tentei isso:
- (void) viewWillDisappear:(BOOL)animated {
// If we are disappearing because we were removed from navigation stack
if (self.navigationController == nil) {
// YOUR CODE HERE
}
[super viewWillDisappear:animated];
}
A idéia é que a popping, navigationController do controlador de visualização está definido para zero. Então, se a vista era a desaparecer, e já tem uma navigationController, eu concluiu-se estalado. (Pode não funcionar em outros cenários).
Não é possível garantir que viewWillDisappear serão chamados popping, uma vez que não é mencionado nos docs. Eu tentei isso quando a vista era vista de cima, e abaixo vista de cima -. E funcionou em ambos
Boa sorte, Oded.
Você pode usar este:
if(self.isMovingToParentViewController)
{
NSLog(@"Pushed");
}
else
{
NSLog(@"Popped");
}
subclasse UINavigationController
e override popViewController
:
Swift 3
protocol CanPreventPopProtocol {
func shouldBePopped() -> Bool
}
class MyNavigationController: UINavigationController {
override func popViewController(animated: Bool) -> UIViewController? {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return nil
}
}
return super.popViewController(animated: animated)
}
//important to prevent UI thread from freezing
//
//if popViewController is called by gesture recognizer and prevented by returning nil
//UI will freeze after calling super.popViewController
//so that, in order to solve the problem we should not return nil from popViewController
//we interrupt the call made by gesture recognizer to popViewController through
//returning false on gestureRecognizerShouldBegin
//
//tested on iOS 9.3.2 not others
func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
let viewController = self.topViewController
if let canPreventPop = viewController as? CanPreventPopProtocol {
if !canPreventPop.shouldBePopped() {
return false
}
}
return true
}
}
Talvez você poderia usar NavigationBar de UINavigationBarDelegate:. Método de protocolo shouldPopItem
Tente fazer essa verificação em viewWillDisappear if ([self.navigationController.viewControllers indexOfObject: self] == NSNotFound) { // popping dessa visão tem happend. }