UISplitViewController带有导航堆栈在主和细节 - 如何从一个堆栈中删除一个VC?
我正在调试总是有趣的遗留代码。旧代码试图模拟代理方法,导致各种问题 - 主要是崩溃:在Portrait中的Plus设备上,旋转到横向导致崩溃 - 如果没有设置详细视图,则旧代码试图在狡猾的黑客和它只是没用...UISplitViewController带有导航堆栈在主和细节 - 如何从一个堆栈中删除一个VC?
我的应用程序是基于UISplitViewController
,其中我在splitView的主和细节两侧都有一个导航堆栈。
通过读取虽然SO和使用this example,并能够实现UISplitViewController
委托方法和一切工作正常关于旋转,并在适当时显示正确的主/细节视图。下面是我的实现:(道歉的代码片段墙)
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
if ([secondaryViewController isKindOfClass:[UINavigationController class]]
&& [[(UINavigationController *)secondaryViewController topViewController] isKindOfClass:[AECourseHTMLTableViewController class]]
&& ([(AECourseHTMLTableViewController *)[(UINavigationController *)secondaryViewController topViewController] htmlContentEntry] == nil)) {
// If the detail controller doesn't have an item, display the primary view controller instead
return YES;
}
return NO;
}
而另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;
}
AECourseHTMLTableViewController
具有下一/先前的按钮在菜单的tableview类类(AEContentMenuTableViewController
)的tableview中选择下一行。我有一个代理功能,可以告诉我当前indexPath
其中AECourseHTML...
正在使用从AEContentMenu...
,并调用它时,它选择菜单tableview行并实例化一个新的AECourseHTML...
并将其推。
这是我卡住的地方。在肖像中,按next/prev很好,它会选择正确的行并按预期工作。但是,一旦我旋转设备,主视图和详细视图都会显示详细视图。我可以在主视图上按“返回”,它将我带到正确的AEContentMenu...
类。如代码片段注释中所述,我需要从主堆栈(实际上是第一个对象)中移除一个ViewController,并且AEContentMenu...
应该成为该堆栈的第一个对象 - 因此在旋转时应该是主视图。
对于这么长的帖子道歉,我已经用了几个星期的时间来敲打我的头,我想在这个问题中尽可能多地包含信息。提前致谢。
我发现了一个适合我的用例的解决方案。它可能不是最干净的代码,但我很满意我得到的。
splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
保持不变。我已经用解决方案更新了我的splitViewController:separateSecondaryViewControllerFromPrimaryViewController:
委托方法。欢迎任何反馈。
- (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;
}