UIViewController的viewDidAppear - 是因为被push了还是子视图被pop了?

6
在我的应用程序中,我有大约十几个不同的视图控制器,以不同的顺序推入或弹出堆栈。当一个视图已经出现(我正在使用 viewDidAppear 方法)时,我需要确定这是因为这个视图刚刚被推到堆栈上,还是因为其中一个子视图从堆栈中弹出。
我查看了这个问题:viewWillDisappear:确定视图控制器是被弹出还是正在显示子视图控制器 但我认为它并没有对我很有帮助。请问你有什么建议吗?
3个回答

4
如果可以的话,最好的解决方案是尝试修改代码,使得控制器被推送或其子级被弹出时不会影响它。从根本上说,视图控制器在其视图和应用程序操作的数据之间进行调节。只要数据是最新的,控制器就不必关心它的视图出现之前发生了什么。你的控制器当前根据应用程序以前的状态执行的任务,例如更新数据,可能真的更适合放在另一个类中。
如果您使用storyboard,则另一种可能性是依赖于-prepareForSegue:sender:而不是-viewDidAppear。在该方法中传递给您的segue具有标识源和目标视图控制器的属性,这通常足以告诉您如何使您的控制器成为当前控制器。
如果以上两种方法都不适用于您的情况,请考虑将配置代码移动到一个或多个不同的方法中。您面临的问题的根源在于-viewWillAppear确实不是您所需要的。创建一个真正满足您需求的方法,如-childControllerFinished,并使用它来执行您需要的配置工作。

1
你可以在视图控制器上创建一个名为alreadyPushed的BOOL属性。然后在viewDidAppear方法中检查它是否为false(第一次调用viewDidAppear时它将是false),如果是,则将其设置为true。
当子视图控制器弹出时,viewDidAppear方法将检查alreadyPushed属性是否设置为true,如果是,则知道刚刚弹出了一个子视图。

谢谢,这似乎是最简单的方法。 - Aleks G

0
如果一个视图控制器被推到了栈上,它的viewDidLoad方法将被调用;如果它的子控制器被弹出,则viewDidLoad不会被调用。
- (void)viewDidLoad {
    [super viewDidLoad];
    //do any setup you want to do only when the view is pushed onto the
    //stack for the first time; this method will not be called
    //when the view's subview is popped and this one becomes visible
}

所以,当视图控制器第一次被推送时,请使用viewDidLoad(或initWithNibName,具体取决于您正在做什么)进行一次性设置,并使用viewDidAppear进行您想要每次显示视图时进行的设置。对于UINavigationController,您可能希望在UINavigationControllerDelegate协议中实现这两种方法:
- (void)navigationController:(UINavigationController *)navigationController 
    willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewWillAppear:animated];
    //do any every-time setup *before* the view is shown
}

- (void)navigationController:(UINavigationController *)navigationController 
    didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    [viewController viewDidAppear:animated];
    //do any every-time setup *after* the view is shown
}

5
不能假定每次将视图控制器添加到导航堆栈时都会调用 -viewDidLoad 方法是安全的。视图控制器可能在使用之前很早就被创建了,而在某个时候其视图也可能被创建。这时才会调用 -viewDidLoad 方法。之后,视图已经加载完成,即使将控制器推入堆栈,该方法也不会被再次调用。 - Caleb
非常好的观点。然而,这似乎不是这种情况。原帖中没有提到预缓存视图控制器的任何内容。 - eric.mitchell
1
@Caleb:这是非常好的一点,特别是对我来说。因为视图控制器被推入和弹出堆栈时,当我弹出一个控制器时,我不会销毁它,而是在需要再次推送它时重新使用它。 - Aleks G

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接