The only solution I have seen was an answer to a stackoverflow question. I posted the link below. The answer I am referring is the 5th one. It seems that some users have so
Inspired by @Lindsey Scott answer I created UINavigationController subclass. The advantage of my solution is that it also handles popping, and you can actually execute all requests after each other without problems(this is controlled via acceptConflictingCommands flag).
MyNavigationController.h
#import
@interface MyNavigationController : UINavigationController
@property(nonatomic, assign) BOOL acceptConflictingCommands;
@end
MyNavigationController.m
#import "MyNavigationController.h"
@interface MyNavigationController ()
@property(nonatomic, assign) BOOL shouldIgnoreStackRequests;
@property(nonatomic, strong) NSMutableArray* waitingCommands;
@end
@implementation MyNavigationController
-(instancetype)init
{
if( self = [super init] )
{
self.delegate = self;
_waitingCommands = [NSMutableArray new];
}
return self;
}
-(instancetype)initWithRootViewController:(UIViewController *)rootViewController
{
if( self = [super initWithRootViewController:rootViewController] )
{
self.delegate = self;
_waitingCommands = [NSMutableArray new];
_acceptConflictingCommands = YES;
}
return self;
}
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
if( !_shouldIgnoreStackRequests )
{
[super pushViewController:viewController animated:animated];
_shouldIgnoreStackRequests = YES;
}
else if (_acceptConflictingCommands)
{
__weak typeof(self) weakSelf = self;
//store and push it after current transition ends
[_waitingCommands addObject:^{
id strongSelf = weakSelf;
[strongSelf pushViewController:viewController animated:animated];
}];
}
}
-(UIViewController *)popViewControllerAnimated:(BOOL)animated
{
__block UIViewController* popedController = nil;
if( 1 < self.viewControllers.count )
{
if( !_shouldIgnoreStackRequests )
{
popedController = [super popViewControllerAnimated:animated];
_shouldIgnoreStackRequests = YES;
}
else if( _acceptConflictingCommands )
{
__weak typeof(self) weakSelf = self;
[_waitingCommands addObject:^{
id strongSelf = weakSelf;
popedController = [strongSelf popViewControllerAnimated:animated];
}];
}
}
return popedController;
}
#pragma mark - uinavigationcontroller delegate
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
_shouldIgnoreStackRequests = NO;
if( 0 < _waitingCommands.count )
{
void(^waitingAction)() = _waitingCommands.lastObject;
[_waitingCommands removeLastObject];
waitingAction();
}
}
@end
Of course you can change default value of acceptConflictingCommands or control it externally.
If your code happens to use popToRootViewController, setViewControllers:animated: and/or popToViewController you have to override them in the same manner to make sure they won't brake navigation stack.