Ios UINavigationController执行事务时发生崩溃

Ios UINavigationController执行事务时发生崩溃,ios,objective-c,uinavigationcontroller,Ios,Objective C,Uinavigationcontroller,我刚刚看到一个崩溃,如下面的屏幕截图所示,它发生在我点击导航栏上的后退按钮时,是否有任何典型情况会导致此崩溃 根据我的经验,iOS 7中引入了一个问题,使您能够在另一个过渡结束之前开始过渡,这最终导致了这次崩溃。如果将两个导航调用背对背放置并运行它们,则可以手动复制这些调用,例如: [self.navigationController pushViewController:whatever animated:YES]; [self.navigationController pushViewCon

我刚刚看到一个崩溃,如下面的屏幕截图所示,它发生在我点击导航栏上的后退按钮时,是否有任何典型情况会导致此崩溃


根据我的经验,iOS 7中引入了一个问题,使您能够在另一个过渡结束之前开始过渡,这最终导致了这次崩溃。如果将两个导航调用背对背放置并运行它们,则可以手动复制这些调用,例如:

[self.navigationController pushViewController:whatever animated:YES];
[self.navigationController pushViewController:whatever2 animated:YES];
如果您这样做,您最终将看到崩溃发生

我发现确保这种情况永远不会发生的最简单的方法是通过子类化
UINavigationController
并实现
UINavigationControllerDelegate
来防止重叠转换

一旦我开始使用下面的代码,我看到的由于这个问题导致的崩溃数量已经下降到0

需要注意的一点是,如果您确实需要实现另一个
,您需要编写一些代码来存储额外的委托,并传递委托调用,可能需要使用
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
@接口MyNavigationController()
{
//用于防止在尝试同时设置两个过渡动画时发生“无法将自身添加为子视图”崩溃
BOOL_当前的动画化;
}
@结束
@MyNavigationController的实现
-(无效)viewDidLoad
{
[超级视图下载];
self.delegate=self;
}
-(void)pushViewController:(UIViewController*)已设置动画的viewController:(BOOL)已设置动画
{
如果(_currentlyAnimating)
{
返回;
}
else if(动画)
{
_currentlyAnimating=是;
}
[超级按钮viewController:viewController动画:动画];
}
-(UIViewController*)PopViewController动画:(BOOL)动画
{
如果(_currentlyAnimating)
{
返回零;
}
else if(动画)
{
_currentlyAnimating=是;
}
返回[超级PopViewController动画:动画];
}
-(void)navigationController:(UINavigationController*)navigationController didShowViewController:(UIViewController*)viewController动画:(BOOL)动画
{
_currentlyAnimating=否;
}
-(void)导航控制器:(UINavigationController*)导航控制器将显示视图控制器:(UIViewController*)视图控制器已设置动画:(BOOL)已设置动画
{
//跟踪取消的交互式pop
// http://stackoverflow.com/questions/23484310/canceling-interactive-uinavigationcontroller-pop-gesture-does-not-call-uinavigat
[[self transitionCoordinator]notifyWhenInteractionEndsUsingBlock:^(id上下文)
{
如果([上下文已取消])
{
UIViewController*fromViewController=[context ViewControllerWorky:UITransitionContextFromViewControllerKey];
[自导航控制器:导航控制器将显示ViewController:fromViewController动画:动画];
if([self-respondsToSelector:@selector(导航控制器:didShowViewController:动画:)]))
{
NSTimeInterval animationCompletion=[context transitionDuration]*[context percentComplete];
调度后(调度时间(立即调度时间,(uint64)动画完成*每秒NSEC),调度获取主队列()^{
[自导航控制器:导航控制器didShowViewController:fromViewController动画:动画];
});
}
}
}];
}
@结束