我正在使用大小类进行通用应用程序,并尝试在主/主视图中使用带有TabBarController的SplitView。在添加splitView之前一切正常,但现在App崩溃了(原因取决于视图的层次结构)。
所以我尝试从Apple SplitView模板开始尝试相同的故事板,并在其主/主视图上添加一个TabBarController ......同样的问题。
层次结构 - TabBarController中的嵌入式主NavigationController: SplitVC(Master)> TabBarController> NavigationController>的TableView SplitVC(详情)> NavigationController>图
在AppDelegate.m中添加了此代码(如stackoverflow questions ios8-tabbarcontroller...所示,以防止以模态方式呈现DetailView):
- (BOOL)splitViewController:(UISplitViewController *)splitViewController showDetailViewController:(UIViewController *)vc sender:(id)sender {
NSLog(@"UISplitViewController collapsed: %d", splitViewController.collapsed);
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
if (splitViewController.collapsed) {
UITabBarController *master = (UITabBarController *) splitViewController.viewControllers[0];
UINavigationController *masterNavigationController = (UINavigationController *)master.selectedViewController;
UINavigationController *destinationNavigationController = (UINavigationController *)vc;
// push detail view on the navigation controller
[masterNavigationController pushViewController:[destinationNavigationController.viewControllers lastObject] animated:YES];
return YES;
}
}
return NO;
}
它运行正常...除非你在iPhone6 Plus中进行模拟,在这种情况下,在以纵向开始并选择一行后,如果你在横向旋转我会看到详细视图作为主要和次要视图。
如果不使用iPhone以纵向方式添加此代码,则会以模态方式显示详细视图,当然也不会显示导航按钮。
修改
经过不同的尝试和一些外在的帮助,我已经向前推进了解决方案。
简短版(请参阅长版以了解您必须执行此操作的原因)
问题的正确解决方案是继承TabBarController,并使其支持一些方法:
@implementation MyTabBarController
- (void)showViewController:(UIViewController *)vc sender:(id)sender
{
if ([self.selectedViewController isKindOfClass:UINavigationController.class])
[self.selectedViewController showViewController:vc sender:sender];
else
[super showViewController:vc sender:sender];
}
- (UIViewController*)separateSecondaryViewControllerForSplitViewController:(UISplitViewController *)splitViewController
{
return [self.selectedViewController separateSecondaryViewControllerForSplitViewController:splitViewController];
}
- (void)collapseSecondaryViewController:(UIViewController *)secondaryViewController forSplitViewController:(UISplitViewController *)splitViewController
{
[self.selectedViewController collapseSecondaryViewController:secondaryViewController forSplitViewController:splitViewController];
}
现在我遇到了viewControllers堆栈的问题:使用iPhone6Plus(唯一一个支持水平常规和紧凑)的应用程序崩溃,如果在横向时,您更改选项卡而不选择行(因此detailView仍然是上一个标签)然后以纵向旋转。
我知道我必须实现正确管理视图堆栈的分离和折叠方法,但我无法弄清楚如何。有人可以提供帮助吗?
长版(SplitViewController行为)
通常分割视图控制器和导航控制器工作 一起确保调用-showDetailViewController:sender: 来自拆分视图中包含的视图控制器 控制器导致新的细节视图控制器被推入 导航堆栈(在水平紧凑的环境中)。至 这样做,UISplitViewController重写 -showDetailViewController:sender:并且,如果是水平紧凑的,则调用其主视图控制器&#sshowViewController:sender:方法。 UINavigationController重写-showViewController:sender:和 将传入的视图控制器推送到导航堆栈。
然而,UITabBarController不会覆盖 -showViewController:sender:所以它继承了默认的实现,它以模态方式呈现传入的视图控制器。 要解决这个问题,我必须继承UITabBarController并重写 -showViewController:sender:如果selectedViewController是导航,则转发到标签栏控制器的selectedViewController 控制器。
此外,当分割视图控制器从紧凑型转换时 将水平尺寸类转换为常规水平尺寸类,拆分 视图控制器首先发送一个 -splitViewController:separateSecondaryViewControllerFromPrimaryViewController: 消息给它的代表。委托可以实现此方法和 处理分离本身,返回详细视图控制器。 如果委托没有实现此方法,或者如果 实现返回nil,拆分视图控制器发送一个 -separateSecondaryViewControllerForSplitViewController:消息到其主视图控制器。主视图控制器应该实现 这种方法来处理分离。 UINavigationController确实如此 实现-separateSecondaryViewControllerForSplitViewController: 它的实现将顶视图控制器弹出导航 堆栈并返回它。因为我使用标签栏控制器作为 主视图控制器,我必须实现 -separateSecondaryViewControllerForSplitViewController:并自行处理分离。
另外,我需要实现自己的折叠逻辑。当拆分视图时 控制器从常规大小类转换为水平大小类 紧凑的水平尺寸类,拆分视图控制器首先发送一个 -splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: 消息给它的代表。委托可以实现此方法和 处理崩溃本身。如果代表没有实现这一点 方法,拆分视图控制器发送一个 -collapseSecondaryViewController:forSplitViewController:消息到其主视图控制器。主视图控制器应该 实现此方法来处理分离。
UINavigationController确实实现了 -collapseSecondaryViewController:forSplitViewController :.它的实现将辅助视图控制器推到了 导航堆栈。因为我使用标签栏控制器作为 主视图控制器,我必须实现 -collapseSecondaryViewController:forSplitViewController:并自行处理崩溃。
答案 0 :(得分:1)
所以,我发现了一些有效的东西,即使它不是标准行为:
- (void)collapseSecondaryViewController:(UIViewController *)secondaryViewController forSplitViewController:(UISplitViewController *)splitViewController
{
[self.selectedViewController.navigationController collapseSecondaryViewController:secondaryViewController forSplitViewController:splitViewController];
}
这相当于YES
委托方法中始终返回splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
。像这样你总是丢弃辅助控制器。
希望这可以帮助别人。
答案 1 :(得分:0)
试试此片段并告诉我们您的搜索结果。此代码段来自stackOverflow(Craig Marvelley)
之外的网站#pragma mark - Split view
// Update secondaryview with the right screen
- (UIViewController *)splitViewController:(UISplitViewController *)splitViewController separateSecondaryViewControllerFromPrimaryViewController:(UIViewController *)primaryViewController {
int tryIt = 0;
if ((IS_IPHONE_6_PLUS) && (isLandscape)) {
if ([primaryViewController isKindOfClass:[UINavigationController class]]) {
for (UIViewController *controller in [(UINavigationController *)primaryViewController viewControllers]) {
tryIt = tryIt + 1;
if ([controller isKindOfClass:[UINavigationController class]] && ([[(UINavigationController *)controller visibleViewController] isKindOfClass:[yourPosibleScreen01 class]] || [[(UINavigationController *)controller visibleViewController] isKindOfClass:[yourPosibleScreen02 class]]) ) {
return controller;
}
// Sublevel where yo are to select the right screen. You must try with a number depends of how many internal hierarchy. But I believe you need number 2 but try it :)
if (tryIt > 2) {
return controller;
}
}
}
// Update detail screen
UIViewController *toViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"YourScreenToShow"];
return toViewController;
}
return nil;
}
- (BOOL)splitViewController:(UISplitViewController *)splitViewController collapseSecondaryViewController:(UIViewController *)secondaryViewController ontoPrimaryViewController:(UIViewController *)primaryViewController {
return NO;
}
#pragma mark - Split view