4

我正在使用大小类做一个通用应用程序,我正在尝试在主视图/主视图中使用带有 TabBarController 的 SplitView。在添加 splitView 之前一切正常,但现在应用程序崩溃(原因取决于视图的层次结构)。

所以我尝试了从 Apple SplitView 模板开始的相同故事板,并在其主视图/主视图上添加了 TabBarController ......同样的问题。

层次结构 - TabBarController 中的嵌入式主 NavigationController:SplitVC (Master) > TabBarController > NavigationController > TableView SplitVC (Detail) > NavigationController > View

在 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: 并且,如果水平紧凑,则调用其主视图控制器的 -showViewController:sender: 方法。UINavigationController 覆盖 -showViewController:sender: 并将传入的视图控制器推送到导航堆栈上。

但是,UITabBarController 不会覆盖 -showViewController:sender: ,因此它继承了以模态方式呈现传入视图控制器的默认实现。要解决这个问题,如果 selectedViewController 是导航控制器,我必须继承 UITabBarController 并覆盖 -showViewController:sender: 以转发到选项卡栏控制器的 selectedViewController。

此外,当拆分视图控制器从紧凑型到水平尺寸类别转换为常规水平尺寸类别时,拆分视图控制器首先向其委托发送 -splitViewController:separateSecondaryViewControllerFromPrimaryViewController: 消息。委托可以实现此方法并自行处理分离,返回详细视图控制器。如果委托没有实现这个方法,或者如果实现返回 nil,则拆分视图控制器发送一个 -separateSecondaryViewControllerForSplitViewController: 消息到它的主视图控制器。主视图控制器应该实现这个方法来处理分离。UINavigationController 确实实现了 -separateSecondaryViewControllerForSplitViewController:。它' s 实现将顶视图控制器从导航堆栈中弹出并返回。因为我使用标签栏控制器作为主视图控制器,所以我必须实现 -separateSecondaryViewControllerForSplitViewController: 并自己处理分离。

我还需要实现我自己的折叠逻辑。当拆分视图控制器从常规大小类转换为紧凑水平大小类时,拆分视图控制器首先向其委托发送 -splitViewController:collapseSecondaryViewController:ontoPrimaryViewController: 消息。委托可以实现此方法并自行处理折叠。如果委托未实现此方法,则拆分视图控制器将 -collapseSecondaryViewController:forSplitViewController: 消息发送到其主视图控制器。主视图控制器应该实现这个方法来处理分离。

UINavigationController 确实实现了 -collapseSecondaryViewController:forSplitViewController:。它的实现将辅助视图控制器推送到导航堆栈上。因为我使用标签栏控制器作为主视图控制器,所以我必须实现 -collapseSecondaryViewController:forSplitViewController: 并自己处理折叠。

4

2 回答 2

1

所以,我发现了一些有用的东西,即使不是标准行为:

- (void)collapseSecondaryViewController:(UIViewController *)secondaryViewController forSplitViewController:(UISplitViewController *)splitViewController
{
    [self.selectedViewController.navigationController collapseSecondaryViewController:secondaryViewController forSplitViewController:splitViewController];
}

这相当于YESsplitViewController:collapseSecondaryViewController:ontoPrimaryViewController:委托方法中总是返回。像这样,您总是丢弃辅助控制器。希望这可以帮助某人。

于 2015-08-16T22:30:15.723 回答
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
于 2015-07-16T02:59:37.133 回答