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…
正在使用fromAEContentMenu…
,调用它时,它选择菜单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;
}