I ran into the same issue.
I was able to come up with a workaround that works really well. I've pushed it up to Github here: https://github.com/jfahrenkrug/UITabBarControllerMoreBugWorkaround
Any improvements are welcome.
The bug happens because the stack of your UINavigationController is removed from it and put into the private UIMoreNavigationController. But upon rotating back to regular width, that stack is not correctly put back into its original UINavigationViewController.
The solution is to subclass UITabBarController and replacing its willTransitionToTraitCollection:withTransitionCoordinator:
with this one:
- (void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
#ifdef MORE_TAB_DEBUG
#define MoreTabDLog(fmt, ...) NSLog((@"[More Tab Debug] " fmt), ##__VA_ARGS__);
#else
#define MoreTabDLog(...)
#endif
MoreTabDLog(@"-- before willTransitionToTraitCollection");
if ((self.traitCollection.horizontalSizeClass != newCollection.horizontalSizeClass) ||
(self.traitCollection.verticalSizeClass != newCollection.verticalSizeClass))
{
if ([self.selectedViewController isKindOfClass:[UINavigationController class]] && [NSStringFromClass([self.selectedViewController class]) hasPrefix:@"UIMore"]) {
#ifdef MORE_TAB_DEBUG
UINavigationController *moreNavigationController = (UINavigationController *)self.selectedViewController;
UIViewController *moreRootViewController = [moreNavigationController topViewController];
MoreTabDLog(@"-- going OUT of compact while on UIMoreList");
MoreTabDLog(@"moreRootViewController: %@", moreRootViewController);
#endif
for (NSInteger overflowVCIndex = 4; overflowVCIndex < [self.viewControllers count]; overflowVCIndex++) {
if ([self.viewControllers[overflowVCIndex] isKindOfClass:[UINavigationController class]]) {
UINavigationController *navigationController = (UINavigationController *)self.viewControllers[overflowVCIndex];
MoreTabDLog(@"popping %@ to root", navigationController);
[navigationController popToRootViewControllerAnimated:NO];
}
}
} else {
BOOL isPotentiallyInOverflow = [self.viewControllers indexOfObject:self.selectedViewController] >= 4;
MoreTabDLog(@"isPotentiallyInOverflow: %i", isPotentiallyInOverflow);
if (isPotentiallyInOverflow && [self.selectedViewController isKindOfClass:[UINavigationController class]]) {
UINavigationController *selectedNavController = (UINavigationController *)self.selectedViewController;
NSArray<UIViewController *> *selectedNavControllerStack = [selectedNavController viewControllers];
MoreTabDLog(@"Selected Nav: %@, selectedNavStack: %@", selectedNavController, selectedNavControllerStack);
UIViewController *lastChildVCOfTabBar = [[self childViewControllers] lastObject];
if ([lastChildVCOfTabBar isKindOfClass:[UINavigationController class]] && [NSStringFromClass([lastChildVCOfTabBar class]) hasPrefix:@"UIMore"]) {
UINavigationController *moreNavigationController = (UINavigationController *)lastChildVCOfTabBar;
NSArray *moreNavigationControllerStack = [moreNavigationController viewControllers];
MoreTabDLog(@"--- going OUT of compact");
MoreTabDLog(@"moreNav: %@, moreNavStack: %@, targetNavStack: %@", moreNavigationController, moreNavigationControllerStack, selectedNavControllerStack);
if ([moreNavigationControllerStack count] > 1) {
NSArray *fixedTargetStack = [moreNavigationControllerStack subarrayWithRange:NSMakeRange(1, moreNavigationControllerStack.count - 1)];
MoreTabDLog(@"fixedTargetStack: %@", fixedTargetStack);
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *correctVCList = [NSArray arrayWithArray:self.viewControllers];
[selectedNavController willMoveToParentViewController:self];
[selectedNavController setViewControllers:fixedTargetStack animated:NO];
[self addChildViewController:selectedNavController];
[self setViewControllers:correctVCList];
});
} else {
MoreTabDLog(@"popping to root");
dispatch_async(dispatch_get_main_queue(), ^{
[selectedNavController popToRootViewControllerAnimated:NO];
});
}
} else {
MoreTabDLog(@"-- going INTO compact");
if ([selectedNavControllerStack count] > 0) {
[coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
} completion:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) {
UIViewController *parentViewControllerOfTopVC = [[selectedNavControllerStack lastObject] parentViewController];
MoreTabDLog(@"parentViewControllerOfTopVC: %@", parentViewControllerOfTopVC);
if ([parentViewControllerOfTopVC isKindOfClass:[UINavigationController class]] && [NSStringFromClass([parentViewControllerOfTopVC class]) hasPrefix:@"UIMore"]) {
UINavigationController *moreNavigationController = (UINavigationController *)parentViewControllerOfTopVC;
NSArray *moreNavigationControllerStack = [moreNavigationController viewControllers];
BOOL isOriginalRootVCInMoreStack = [moreNavigationControllerStack containsObject:[selectedNavControllerStack firstObject]];
MoreTabDLog(@"moreNav: %@, moreNavStack: %@, isOriginalRootVCInMoreStack: %i", moreNavigationController, moreNavigationControllerStack, isOriginalRootVCInMoreStack);
if (!isOriginalRootVCInMoreStack) {
NSArray *fixedMoreStack = [@[moreNavigationControllerStack[0]] arrayByAddingObjectsFromArray:selectedNavControllerStack];
MoreTabDLog(@"fixedMoreStack: %@", fixedMoreStack);
[selectedNavController setViewControllers:selectedNavControllerStack animated:NO];
dispatch_async(dispatch_get_main_queue(), ^{
[moreNavigationController setViewControllers:fixedMoreStack animated:NO];
});
}
}
}];
}
}
}
}
}
[super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
MoreTabDLog(@"-- after willTransitionToTraitCollection");
}
Enjoy!
Johannes
Unbalanced calls to begin/end appearance transitions for <UIViewController: 0x7faa186db7b0>
but it shouldn't be. I don't have iPhone 6s plus so please test on the device first. It might be bug of simulator. – Ryansize class
but not sure. – Ryan