Skip to content

Instantly share code, notes, and snippets.

@nonamelive
Last active April 21, 2023 06:56
Show Gist options
  • Save nonamelive/9334458 to your computer and use it in GitHub Desktop.
Save nonamelive/9334458 to your computer and use it in GitHub Desktop.
Prevent UINavigationController from pushing two view controllers at the same time in case of stack inconsistency and crashes
@interface UINavigationController (DMNavigationController)
- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;
@end
@interface DMNavigationController ()
@property (nonatomic, assign) BOOL shouldIgnorePushingViewControllers;
@end
@implementation DMNavigationViewController
#pragma mark - Push
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if (!self.shouldIgnorePushingViewControllers)
{
[super pushViewController:viewController animated:animated];
}
self.shouldIgnorePushingViewControllers = YES;
}
#pragma mark - Private API
// This is confirmed to be App Store safe.
// If you feel uncomfortable to use Private API, you could also use the delegate method navigationController:didShowViewController:animated:.
- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[super didShowViewController:viewController animated:animated];
self.shouldIgnorePushingViewControllers = NO;
}
@bpoplauschi
Copy link

Very good idea, thanks.

@heikkihautala
Copy link

This could be improved to store concurrent push actions and execute them synchronously one after another. What do you think?

@jaybowang
Copy link

Is there a way to reproduce the crash that this code tries to solve?
I like @heikkihautala 's idea and I'm trying to implement it. But I have to make sure that my code solves the crash too.

@TimchenKKBOX
Copy link

We had the same issue as @whychengxiaogang said, it will not enter push flow if swipe from edge to right for poping view controller but not actually pop, just be in middle state of pushing.

our workaournd: in view controller :

  • (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    staticMember.shouldIgnorePushingViewControllers = YES;
    }

  • (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:NO];
    staticMember.shouldIgnorePushingViewControllers = NO;
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment