Ios UISplitViewController在主堆栈和详细堆栈中都具有导航堆栈-如何从其中一个堆栈中删除VC?

Ios UISplitViewController在主堆栈和详细堆栈中都具有导航堆栈-如何从其中一个堆栈中删除VC?,ios,objective-c,uinavigationcontroller,uisplitviewcontroller,iphone-6-plus,Ios,Objective C,Uinavigationcontroller,Uisplitviewcontroller,Iphone 6 Plus,我正在调试遗留代码,这总是很有趣的。旧代码试图模仿splitViewdelegate方法,导致了各种各样的问题——主要是崩溃:在纵向的加号设备上,旋转到横向导致了崩溃——如果没有细节视图集,旧代码试图在一次狡猾的黑客攻击中创建一个,但毫无用处 我的应用程序基于UISplitViewController,在splitView的主视图和详细视图中都有一个导航堆栈 通过阅读Through SO,使用并能够实现UISplitViewController委托方法,旋转方面一切正常,并在适当时显示正确的主视

我正在调试遗留代码,这总是很有趣的。旧代码试图模仿
splitView
delegate方法,导致了各种各样的问题——主要是崩溃:在纵向的加号设备上,旋转到横向导致了崩溃——如果没有细节视图集,旧代码试图在一次狡猾的黑客攻击中创建一个,但毫无用处

我的应用程序基于
UISplitViewController
,在splitView的主视图和详细视图中都有一个导航堆栈

通过阅读Through SO,使用并能够实现
UISplitViewController
委托方法,旋转方面一切正常,并在适当时显示正确的主视图/详细视图。这是我的实现:(为代码片段墙道歉)

还有另一个splitView委托方法——请参阅代码中的注释,了解我的困境

- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController {
    // If detail view already exists
    if ([primaryViewController isKindOfClass:[UINavigationController class]]) {
        for (UIViewController *controller in [(UINavigationController *)primaryViewController viewControllers]) {
            if ([controller isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)controller visibleViewController] isKindOfClass:[AECourseHTMLTableViewController class]]) {
                return controller;
            }
        }
    }

    // Create detail view
    UINavigationController *navController = [self.storyboard instantiateViewControllerWithIdentifier:@"CourseHTMLNav"];
    if ([navController.viewControllers.firstObject isKindOfClass:[AECourseHTMLTableViewController class]]) {
    AECourseHTMLTableViewController *courseViewController = navController.viewControllers.firstObject;
    [self configureViewController:courseViewController entry:self.contentSection.sections[0] indexPath:courseViewController.currentIndexPath];
    }

    // Enable back button
    UIViewController *controller = [navController visibleViewController];
    controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
    controller.navigationItem.leftItemsSupplementBackButton = YES;

    if (!self.splitViewController.isCollapsed) {
        UINavigationController *navController = self.splitViewController.viewControllers.firstObject;
        AEContentMenuTableViewController *contentMenuVC = navController.viewControllers.firstObject; // This controller needs to be master in Landscape

        NSMutableArray<UIViewController *> *controllers = [navController.viewControllers mutableCopy]; // Contains 3 controllers, first needs removed
        NSMutableArray *toDelete = [NSMutableArray new];

    for (UIViewController *viewController in controllers)
        if ([viewController isKindOfClass:[contentMenuVC class]] || [viewController isKindOfClass:[AECourseHTMLTableViewController class]]) {
            [toDelete addObject:viewController]; // Remove first VC, so master should become AEContentMenuVC?
            break;
        }

    // Remove the object
    [controllers removeObjectsInArray:toDelete];

    // Set viewControllers
    navController.viewControllers = controllers;
    }
    return navController;
  }
-(UIViewController*)拆分视图控制器:(UISplitViewController*)拆分视图控制器分离来自primaryViewController的第二视图控制器:(UIViewController*)primaryViewController{
//如果详图视图已存在
if([primaryViewController是类的种类:[UINavigationController类]]){
对于[(UINavigationController*)primaryViewController ViewController]中的(UIViewController*控制器){
如果([controller iskindof类:[UINavigationController类]]&&[(UINavigationController*)controller visibleViewController]iskindof类:[AECourseHTMLTableViewController类]]){
返回控制器;
}
}
}
//创建局部视图
UINavigationController*navController=[self.storyboard实例化eviewcontrollerwhithidentifier:@“CourseHTMLNav”];
如果([navController.ViewController.firstObject是类:[AECourseHTMLTableViewController类]]){
AECourseHTMLTableViewController*courseViewController=navController.ViewController.firstObject;
[self-configureViewController:courseViewController条目:self.contentSection.sections[0]索引XPath:courseViewController.currentIndexPath];
}
//启用后退按钮
UIViewController*控制器=[navController visibleViewController];
controller.navigationItem.leftBarButtonItem=self.splitViewController.displayModeButtonItem;
controller.navigationItem.LeftItemsSupportElementBackButton=是;
如果(!self.splitViewController.isCollapsed){
UINavigationController*navController=self.splitViewController.viewControllers.firstObject;
AEContentMenuTableViewController*contentMenuVC=navController.ViewController.firstObject;//此控制器需要在横向环境中处于主控状态
NSMutableArray*控制器=[navController.ViewController mutableCopy];//包含3个控制器,首先需要删除
NSMUTABLEARRY*toDelete=[NSMUTABLEARRY new];
用于(UIViewController*控制器中的viewController)
if([viewController IsKindof类:[contentMenuVC类]]| |[viewController IsKindof类:[AECourseHTMLTableViewController类]])){
[toDelete addObject:viewController];//删除第一个VC,那么master应该成为AEContentMenuVC吗?
打破
}
//移除对象
[控制器removeObjectsInArray:toDelete];
//设置视图控制器
navController.viewControllers=控制器;
}
返回导航控制器;
}
AECourseHTMLTableViewController
具有next/prev按钮,用于选择tableview菜单类的tableview中的下一行(
AEContentMenuTableViewController
)。我有一个委托函数,它可以告诉我当前的
indepath
,其中
AECourseHTML…
正在使用from
AEContentMenu…
,调用它时,它选择菜单tableview行,实例化一个新的
AECourseHTML…
,并推送它

这就是我被困的地方。在纵向中,按next/prev可以选择正确的行并按预期工作。但一旦我旋转设备,主视图和详细视图都会显示详细视图。我可以在主视图上按“后退”,它会将我带到正确的
AEContentMenu…
class。如代码段注释中所述,我需要从主堆栈中删除ViewController(实际上是第一个对象),并且
AEContentMenu…
应该成为该堆栈的第一个对象-因此,旋转时,这应该是主视图


为这么长的帖子道歉,几个星期以来我一直在为这个问题绞尽脑汁,我想在这个问题中包含尽可能多的信息。提前感谢。

我找到了一个适合我的用例的解决方案。这可能不是最干净的代码,但我很满意我所拥有的

splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
保持不变。我已经用解决方案更新了我的
splitViewController:separateSecondaryViewControllerFromPrimaryViewController:
delegate方法。欢迎任何反馈

- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController {
   // If detail view already exists
   if ([primaryViewController isKindOfClass:[UINavigationController class]]) {
       for (UIViewController *controller in [(UINavigationController *)primaryViewController viewControllers]) {
           if ([controller isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)controller visibleViewController] isKindOfClass:[AECourseHTMLTableViewController class]]) {
               return controller;
           }
       }
   }

   // Return CourseVC
   UINavigationController *navController = splitViewController.viewControllers.firstObject;
   UIViewController *viewController;
   for (viewController in navController.viewControllers) {
       if ([navController.viewControllers.lastObject isKindOfClass:[AECourseHTMLTableViewController class]]) {
           return viewController;
       } else {
           // Create detail view
           UINavigationController *navController = [self.storyboard instantiateViewControllerWithIdentifier:@"CourseHTMLNav"];
           if ([navController.viewControllers.firstObject isKindOfClass:[AECourseHTMLTableViewController class]]) {

               // Enable back button
               UIViewController *controller = [navController visibleViewController];
               controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
               controller.navigationItem.leftItemsSupplementBackButton = YES;

               AECourseHTMLTableViewController *courseViewController = navController.viewControllers.firstObject;
               // If next/prev has been tapped, configure current ContentHTML
               if (self.currentContentHTML) {
                   [self configureViewController:courseViewController entry:self.currentContentHTML indexPath:courseViewController.currentIndexPath];
               } else {
                   // Create new ContentHTML from first row of AEContentMenuVC
                   [self configureViewController:courseViewController entry:self.contentSection.sections[0] indexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
               }
               return navController;
           }
         }
   }
   return navController;
}

您的top if语句应该返回nil。由于您返回嵌套的导航控制器,因此错过了弹出主导航的顶部控制器的默认行为,这是必需的,因此可以将其放置在右侧

默认行为将找到嵌套的导航控制器并将其弹出。然而,您仍然需要自己搜索它的原因是,如果它不在那里,那么您需要像您所做的那样从故事板加载细节导航

- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController {
   // If detail view already exists
   if ([primaryViewController isKindOfClass:[UINavigationController class]]) {
       for (UIViewController *controller in [(UINavigationController *)primaryViewController viewControllers]) {
           if ([controller isKindOfClass:[UINavigationController class]] && [[(UINavigationController *)controller visibleViewController] isKindOfClass:[AECourseHTMLTableViewController class]]) {
               return controller;
           }
       }
   }

   // Return CourseVC
   UINavigationController *navController = splitViewController.viewControllers.firstObject;
   UIViewController *viewController;
   for (viewController in navController.viewControllers) {
       if ([navController.viewControllers.lastObject isKindOfClass:[AECourseHTMLTableViewController class]]) {
           return viewController;
       } else {
           // Create detail view
           UINavigationController *navController = [self.storyboard instantiateViewControllerWithIdentifier:@"CourseHTMLNav"];
           if ([navController.viewControllers.firstObject isKindOfClass:[AECourseHTMLTableViewController class]]) {

               // Enable back button
               UIViewController *controller = [navController visibleViewController];
               controller.navigationItem.leftBarButtonItem = self.splitViewController.displayModeButtonItem;
               controller.navigationItem.leftItemsSupplementBackButton = YES;

               AECourseHTMLTableViewController *courseViewController = navController.viewControllers.firstObject;
               // If next/prev has been tapped, configure current ContentHTML
               if (self.currentContentHTML) {
                   [self configureViewController:courseViewController entry:self.currentContentHTML indexPath:courseViewController.currentIndexPath];
               } else {
                   // Create new ContentHTML from first row of AEContentMenuVC
                   [self configureViewController:courseViewController entry:self.contentSection.sections[0] indexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
               }
               return navController;
           }
         }
   }
   return navController;
}