ios viewWillDisappear:判断视图控制器是被弹出还是正在显示子视图控制器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1816614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
viewWillDisappear: Determine whether view controller is being popped or is showing a sub-view controller
提问by Michael Waterfall
I'm struggling to find a good solution to this problem. In a view controller's -viewWillDisappear:
method, I need to find a way to determine whether it is because a view controller is being pushed onto the navigation controller's stack, or whether it is because the view controller is disappearing because it has been popped.
我正在努力寻找解决这个问题的好方法。在视图控制器的-viewWillDisappear:
方法中,我需要找到一种方法来确定是因为视图控制器被推送到导航控制器的堆栈上,还是因为视图控制器因为被弹出而消失。
At the moment I'm setting flags such as isShowingChildViewController
but it's getting fairly complicated. The only way I think I can detect it is in the -dealloc
method.
目前我正在设置标志,isShowingChildViewController
但它变得相当复杂。我认为我可以检测到它的唯一方法是在-dealloc
方法中。
回答by Bryan Henry
You can use the following.
您可以使用以下内容。
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
NSArray *viewControllers = self.navigationController.viewControllers;
if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {
// View is disappearing because a new view controller was pushed onto the stack
NSLog(@"New view controller was pushed");
} else if ([viewControllers indexOfObject:self] == NSNotFound) {
// View is disappearing because it was popped from the stack
NSLog(@"View controller was popped");
}
}
This is, of course, possible because the UINavigationController's view controller stack (exposed through the viewControllers property) has been updated by the time that viewWillDisappear is called.
这当然是可能的,因为 UINavigationController 的视图控制器堆栈(通过 viewControllers 属性公开)已在调用 viewWillDisappear 时更新。
回答by RTasche
I think the easiest way is:
我认为最简单的方法是:
- (void)viewWillDisappear:(BOOL)animated
{
if ([self isMovingFromParentViewController])
{
NSLog(@"View controller was popped");
}
else
{
NSLog(@"New view controller was pushed");
}
[super viewWillDisappear:animated];
}
Swift:
迅速:
override func viewWillDisappear(animated: Bool)
{
if isMovingFromParent
{
print("View controller was popped")
}
else
{
print("New view controller was pushed")
}
super.viewWillDisappear(animated)
}
回答by Shyam Bhat
From Apple's Documentation in UIViewController.h :
来自 UIViewController.h 中的 Apple 文档:
"These four methods can be used in a view controller's appearance callbacks to determine if it is being presented, dismissed, or added or removed as a child view controller. For example, a view controller can check if it is disappearing because it was dismissed or popped by asking itself in its viewWillDisappear: method by checking the expression ([self isBeingDismissed] || [self isMovingFromParentViewController])."
- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);
- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);
“这四种方法可以在视图控制器的外观回调中使用,以确定它是否作为子视图控制器被呈现、关闭或添加或删除。例如,视图控制器可以检查它是否因为被关闭或被关闭而消失。通过检查表达式 ([self isBeingDismissed] || [self isMovingFromParentViewController]) 在它的 viewWillDisappear: 方法中询问自己弹出。”
- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);
- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);
So yes, the only documented way to do this is the following way :
所以是的,唯一记录在案的方法是以下方式:
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if ([self isBeingDismissed] || [self isMovingFromParentViewController]) {
}
}
Swift 3 version:
斯威夫特 3 版本:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if self.isBeingDismissed || self.isMovingFromParentViewController {
}
}
回答by dk.
If you just want to know whether your view is getting popped, I just discovered that self.navigationController
is nil
in viewDidDisappear
, when it is removed from the stack of controllers. So that's a simple alternative test.
如果你只是想知道你的观点是否得到弹出,我才发现,原来self.navigationController
是nil
在viewDidDisappear
,当它从控制器的堆栈中删除。所以这是一个简单的替代测试。
(This I discover after trying all sorts of other contortions. I'm surprised there's no navigation controller protocol to register a view controller to be notified on pops. You can't use UINavigationControllerDelegate
because that actually does real display work.)
(这是我在尝试各种其他扭曲后发现的。我很惊讶没有导航控制器协议来注册要在弹出窗口中通知的视图控制器。您不能使用,UINavigationControllerDelegate
因为它实际上确实进行了真正的显示工作。)
回答by Umair
Swift 4
斯威夫特 4
override func viewWillDisappear(_ animated: Bool)
{
super.viewWillDisappear(animated)
if self.isMovingFromParent
{
//View Controller Popped
}
else
{
//New view controller pushed
}
}
回答by user754905
In Swift:
在斯威夫特:
override func viewWillDisappear(animated: Bool) {
if let navigationController = self.navigationController {
if !contains(navigationController.viewControllers as! Array<UIViewController>, self) {
}
}
super.viewWillDisappear(animated)
}
回答by Norman
I find Apple's documentation on this is hard to understand. This extension helps see the states at each navigation.
我发现 Apple 的文档很难理解。此扩展有助于查看每个导航的状态。
extension UIViewController {
public func printTransitionStates() {
print("isBeingPresented=\(isBeingPresented)")
print("isBeingDismissed=\(isBeingDismissed)")
print("isMovingToParentViewController=\(isMovingToParentViewController)")
print("isMovingFromParentViewController=\(isMovingFromParentViewController)")
}
}
回答by dengST30
Thanks @Bryan Henry, Still works in Swift 5
感谢@Bryan Henry,仍然可以在 Swift 5 中使用
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let controllers = navigationController?.children{
if controllers.count > 1, controllers[controllers.count - 2] == self{
// View is disappearing because a new view controller was pushed onto the stack
print("New view controller was pushed")
}
else if controllers.firstIndex(of: self) == nil{
// View is disappearing because it was popped from the stack
print("View controller was popped")
}
}
}
回答by user1396236
This question is fairly old but I saw it by accident so I want to post best practice (afaik)
这个问题相当古老,但我偶然看到了它,所以我想发布最佳实践(afaik)
you can just do
你可以做
if([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
// view controller popped
}
回答by Byte
This applies to iOS7, no idea if it applies to any other ones. From what I know, in viewDidDisappear
the view already has been popped. Which means when you query self.navigationController.viewControllers
you will get a nil
. So just check if that is nil.
这适用于iOS7,不知道它是否适用于任何其他。据我所知,在viewDidDisappear
视图中已经弹出。这意味着当您查询时,self.navigationController.viewControllers
您将得到一个nil
. 所以只需检查这是否为零。
TL;DR
TL; 博士
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
if (self.navigationController.viewControllers == nil) {
// It has been popped!
NSLog(@"Popped and Gone");
}
}