确定导航是子视图控制器中的弹出还是推送

时间:2015-08-12 07:55:26

标签: ios

不幸的是,isMovingToParentViewController无法在子视图控制器中工作。在我的情况下,它总是在viewWillDisappear中返回NO。

重现步骤:

  1. 创建自定义容器视图控制器。
  2. 在其中添加子视图控制器。
  3. 将容器嵌入UINavigationController
  4. 在子视图控制器的viewWillDisappear:中编写测试代码。
  5. 推送容器然后返回,验证viewWillDisappear:方法中isMovingToParentViewController始终是NO
  6. 问题

    如果它是儿童视图控制器,有没有办法知道导航方向丢弃?

    或者在实现容器视图控制器时我需要注意什么?

2 个答案:

答案 0 :(得分:1)

更新答案

原始答案的基础(下文)仍然有效。我们会在容器视图控制器中使用isMovingToParentViewControllerisMovingFromParentViewController来确定推送/弹出,然后通知嵌入式(或儿童)查看控制器。

为了使其尽可能灵活(可能有许多嵌入的UIViewController子类)我已经定义了EmbeddableViewController类别。

@protocol EmbeddableViewController <NSObject>

- (void)embeddable_isBeingPushedOntoNavigationController:(UINavigationController *)navigationController;

- (void)embeddable_isBeingPoppedOffNavigationController:(UINavigationController *)navigationController;

@end

每个嵌入式/子视图控制器都需要符合此协议:

@interface EmbeddedViewController : UIViewController <EmbeddableViewController>

@end

@implementation EmbeddedViewController

- (void)embeddable_isBeingPushedOntoNavigationController:(UINavigationController *)navigationController {
    // do whatever
}

- (void)embeddable_isBeingPoppedOffNavigationController:(UINavigationController *)navigationController {
    // do whatever
}

@end

容器视图控制器需要在prepareForSegue:sender:方法中获取对嵌入式视图控制器的引用,检测推/弹导航并通知嵌入式视图控制器:

@interface OuterViewController ()
// Keep a reference to the embedded controller
@property (nonatomic, strong) UIViewController<EmbeddableViewController>* embeddedViewController;

@end

@implementation OuterViewController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self notifyEmbeddedViewControllerOfNavigation];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self notifyEmbeddedViewControllerOfNavigation];
}

- (void)notifyEmbeddedViewControllerOfNavigation {

    if ([self isMovingToParentViewController]) {
        [self.embeddedViewController embeddable_isBeingPushedOntoNavigationController:self.navigationController];
    } else if ([self isMovingFromParentViewController]) {
        [self.embeddedViewController embeddable_isBeingPoppedOffNavigationController:self.navigationController];
    }

}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    [super prepareForSegue:segue sender:sender];

    // Assuming the storyboard has set the embed segue's identifier to "Embedded"
    if ([segue.identifier isEqualToString:@"Embedded"]) {
        self.embeddedViewController = segue.destinationViewController;
    }
}

@end

来自updated sample project的控制台输出:

2015-08-12 09:51:41.900 stack2[2263:569042] OuterViewController Is being pushed
2015-08-12 09:51:41.901 stack2[2263:569042] EmbeddedViewController -[EmbeddedViewController embeddable_isBeingPushedOntoNavigationController:]
2015-08-12 09:51:42.777 stack2[2263:569042] OuterViewController Is being pushed
2015-08-12 09:51:42.778 stack2[2263:569042] EmbeddedViewController -[EmbeddedViewController embeddable_isBeingPushedOntoNavigationController:]
2015-08-12 09:51:44.037 stack2[2263:569042] OuterViewController Is being pushed
2015-08-12 09:51:44.037 stack2[2263:569042] EmbeddedViewController -[EmbeddedViewController embeddable_isBeingPushedOntoNavigationController:]
2015-08-12 09:51:44.777 stack2[2263:569042] OuterViewController Is being popped
2015-08-12 09:51:44.777 stack2[2263:569042] EmbeddedViewController -[EmbeddedViewController embeddable_isBeingPoppedOffNavigationController:]
2015-08-12 09:51:45.409 stack2[2263:569042] OuterViewController Is being popped
2015-08-12 09:51:45.410 stack2[2263:569042] EmbeddedViewController -[EmbeddedViewController embeddable_isBeingPoppedOffNavigationController:]
2015-08-12 09:51:46.174 stack2[2263:569042] OuterViewController Is being popped
2015-08-12 09:51:46.174 stack2[2263:569042] EmbeddedViewController -[EmbeddedViewController embeddable_isBeingPoppedOffNavigationController:]

原始答案

来自isMovingToParentViewController的文档:

  

此方法仅在从内部调用时返回YES   viewWillAppear:和viewDidAppear:methods。

isMovingFromParentViewController

  

此方法仅在从内部调用时返回YES   viewWillDisappear:和viewDidDisappear:methods。

有了这些知识,子视图控制器可以确定导航是推送还是流行...

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self checkNavigationDirection];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    [self checkNavigationDirection];
}

- (void)checkNavigationDirection {
    if ([self isMovingToParentViewController]) {
        NSLog(@"%p Is being pushed", self);
    }
    else if ([self isMovingFromParentViewController]) {
        NSLog(@"%p Is being popped", self);
    }
}

在按下3个视图控制器后,(样本)控制台输出结果,然后弹出3个视图控制器:

2015-08-12 09:10:56.296 stack2[1487:358827] 0x7fff09e0bba0 Is being pushed
2015-08-12 09:10:57.420 stack2[1487:358827] 0x7fff09f6b980 Is being pushed
2015-08-12 09:10:58.365 stack2[1487:358827] 0x7fff09c2f800 Is being pushed
2015-08-12 09:10:59.167 stack2[1487:358827] 0x7fff09c2f800 Is being popped
2015-08-12 09:10:59.782 stack2[1487:358827] 0x7fff09f6b980 Is being popped
2015-08-12 09:11:00.311 stack2[1487:358827] 0x7fff09e0bba0 Is being popped

随意下载sample project

答案 1 :(得分:0)

来自the docs for isMovingFromParentViewController

  

此方法仅在从内部调用时返回YES   viewWillDisappear:viewDidDisappear:方法。

isMovingToParentViewController

  

此方法仅在从内部调用时返回YES   viewWillAppear:viewDidAppear:方法。

因此,如果它适合在此处使用此信息,请将代码移至这些视图外观方法。

如果没有,您将不得不自己实施某种逻辑。这可能涉及容器控制器将Bool传递给子视图控制器以进行每次转换,或者在容器控制器上具有返回所需信息的委托方法。