带有UIAlertController的UINavigationController被另外解散

时间:2017-10-12 13:02:07

标签: ios objective-c uinavigationcontroller uialertcontroller

我得到了这个UIAlertController,我在最顶层的视图控制器上以模态方式呈现,如下所示:

UIViewController *top = [Utility topController];

UIAlertController *alertController
= [UIAlertController alertControllerWithTitle:@"Error"
                                      message:@"input string too long"
                               preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction *ok = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
  }];

[alertController addAction:ok];

UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
  }];

[alertController addAction:cancel];

[top presentViewController:alertController
                  animated:true
                completion:nil];
}

我找到最顶层视图控制器的方法是循环显示所提供的视图控制器,并确保我不会出现在警报控制器之上:

+ (UIViewController *)topController {
  UIViewController *topController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];

  while (topController.presentedViewController) {
    if ([topController.presentedViewController class] == [UIAlertController class]) {
      [topController.presentedViewController dismissViewControllerAnimated:YES completion:nil];
      break;
    }
    topController = topController.presentedViewController;
  }
  return topController;
}

这一切都很好,无论UIViewController,顶级控制器都呈现UIAlertController,因为它是presentedViewController。当我点击确定或取消时,UIAlertController被隐式解雇。但是,我有一个自定义UINavigationController,它被呈现在上面,并且由于某种原因,UINavigationController也被覆盖dismissViewControllerAnimated:被调用。

- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
    [super dismissViewControllerAnimated:flag completion:completion];
}

为什么UINavigationControllerpresentedViewController被解雇,以及它自己被解雇了?我应该补充一点,我这样提出UINavigationController

[self presentViewController:nav animated:YES completion:nil];

为什么dismissViewControllerAnimated:似乎被调用了两次?是否应该仅对dismissViewControllerAnimated UINavigationController的{​​{1}}调用presentedViewController隐式调用?

1 个答案:

答案 0 :(得分:0)

你在“顶级”代码中调用dismissViewController,这根本不对我有任何意义。

无论呈现任何UIAlertController都应该在显示警报后返回,因此在任何给定的时间点应该只有一个UIAlertController处于活动状态,因此在尝试查找最顶层的viewController以显示新的UIAlertController时无需解除之前的UIAlertController 。您不想随意解除用户的警报;你的应用需要告诉用户一些东西,所以让他们决定何时完成阅读。

建议更改:

使用类别查找当前的viewController

@implementation UIViewController (Current)

#import "UIViewController+Current.h"

@implementation UIViewController (Current)

+(UIViewController*) findBestViewController:(UIViewController*)vc {

    if (vc.presentedViewController) {

        // Return presented view controller
        return [UIViewController findBestViewController:vc.presentedViewController];

    } else if ([vc isKindOfClass:[UISplitViewController class]]) {

        // Return right hand side
        UISplitViewController* svc = (UISplitViewController*) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController findBestViewController:svc.viewControllers.lastObject];
        else
            return vc;

    } else if ([vc isKindOfClass:[UINavigationController class]]) {

        // Return top view
        UINavigationController* svc = (UINavigationController*) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController findBestViewController:svc.topViewController];
        else
            return vc;

    } else if ([vc isKindOfClass:[UITabBarController class]]) {

        // Return visible view
        UITabBarController* svc = (UITabBarController*) vc;
        if (svc.viewControllers.count > 0)
            return [UIViewController findBestViewController:svc.selectedViewController];
        else
            return vc;

    } else {

        // Unknown view controller type, return last child view controller
        return vc;

    }

}
+(UIViewController*) currentViewController {
    // Find best view controller
    UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
    return [UIViewController findBestViewController:viewController];
}

.h文件

#import <UIKit/UIKit.h>

@interface UIViewController (Current)

+(UIViewController*) currentViewController;

@end

然后更改“顶部”行以使用它

UIViewController *top = [UIViewController currentViewController];