【问题标题】:Crash happened when UINavigationController doing transactionUINavigationController 执行事务时发生崩溃
【发布时间】:2014-07-16 20:22:37
【问题描述】:

我刚刚遇到如下截图所示的崩溃,当我点击导航栏上的返回按钮时发生了这种情况,是否有任何典型情况会导致这种崩溃?

【问题讨论】:

    标签: ios objective-c uinavigationcontroller


    【解决方案1】:

    根据我的经验,iOS 7 中引入了一个问题,使您可以在另一个过渡结束之前开始过渡,这最终导致了这次崩溃。如果您将 2 个导航调用背靠背并运行它们,则可以手动重现此操作,例如:

    [self.navigationController pushViewController:whatever animated:YES];
    [self.navigationController pushViewController:whatever2 animated:YES];
    

    如果你这样做,你最终会看到崩溃发生。

    我发现确保这种情况永远不会发生的最简单方法是继承 UINavigationController 并实现 UINavigationControllerDelegate 以防止重叠转换。

    一旦我开始使用下面的代码,我看到的由于此问题而导致的崩溃次数已降至 0。

    需要注意的一点是,如果您确实需要实现另一个 <UINavigationControllerDelegate>,您将需要编写一些代码来自己存储额外的委托并传递委托调用,可能使用 NSProxy 或类似的东西。

    @interface MyNavigationController () <UINavigationControllerDelegate>
    {
        // used to prevent "can't add self as subview" crashes which occur when trying to animate 2 transitions simultaneously
        BOOL _currentlyAnimating;
    }
    
    @end
    
    @implementation MyNavigationController
    
    - (void) viewDidLoad
    {
        [super viewDidLoad];
        self.delegate = self;
    }
    
    - (void) pushViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        if(_currentlyAnimating)
        {
            return;
        }
        else if(animated)
        {
            _currentlyAnimating = YES;
        }
    
        [super pushViewController:viewController animated:animated];
    }
    
    - (UIViewController *) popViewControllerAnimated:(BOOL)animated
    {
        if(_currentlyAnimating)
        {
            return nil;
        }
        else if(animated)
        {
            _currentlyAnimating = YES;
        }
    
        return [super popViewControllerAnimated:animated];
    
    }
    
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        _currentlyAnimating = NO;
    }
    
    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        // tracking cancelled interactive pop
        // http://stackoverflow.com/questions/23484310/canceling-interactive-uinavigationcontroller-pop-gesture-does-not-call-uinavigat
        [[self transitionCoordinator] notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context)
        {
            if([context isCancelled])
            {
                UIViewController *fromViewController = [context viewControllerForKey:UITransitionContextFromViewControllerKey];
                [self navigationController:navigationController willShowViewController:fromViewController animated:animated];
    
                if([self respondsToSelector:@selector(navigationController:didShowViewController:animated:)])
                {
                    NSTimeInterval animationCompletion = [context transitionDuration] * [context percentComplete];
    
                    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (uint64_t)animationCompletion * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                        [self navigationController:navigationController didShowViewController:fromViewController animated:animated];
                    });
                }
    
    
            }
        }];
    }
    
    @end
    

    【讨论】:

      猜你喜欢
      • 2022-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-14
      • 2011-03-24
      • 2019-10-06
      相关资源
      最近更新 更多