UISplitViewController不能作为根视图控制器

11
我正在开发我的第一个iPad应用程序。其中之一的需求是处理UISplitviewcontroller和UINavigationController。
我们提出的视图层次结构是

(登录页面) ->导航视图(主视图+集合视图)-> UISplitViewcontroller(详情视图)。

我们的应用程序仅支持横向模式
我参考了SO问题(以及GILT应用程序),作为新手,很难根据描述完成它。

所以我的问题是
1)有人能给我一些小的代码片段或教程来实现同样的事情吗?
2)根据苹果的HIG,UISplitviewcontroller应该是rootviewcontroller,如果不是会怎么样?苹果会拒绝我的应用程序吗?(显然GILT Group已经被批准)
3)我发现MGSplitViewController,我可以将其用作非根节点吗?
任何帮助都将不胜感激。作为新手,我希望我的问题是真诚的。
5个回答

13

如果想要使用开箱即用的splitView,则必须将其设置为根视图;在此进行任何胡乱操作都会破坏苹果的指南或表现出异常行为。

MGSplitViewController是SplitViewController的完全自定义实现。如果您需要这种功能,它非常好,但其中一些功能基于我们的应用程序会定向的事实。

或者,您可以创建自己的SplitViewController。我已经做过这个超过一次,比听起来容易。

(LoginView) ->UINavigationView(LandingView + CollectionView)->UISplitViewcontroller( DetailsView)。

基于开箱即用的UISplitView,我建议:

  • 使splitView成为根视图。

  • 在应用程序启动时立即弹出(非动画)全屏模态窗口,并允许用户在其中浏览loginView、LandingView和collectionView;我还建议在此处使用navController。

  • 一旦用户准备好继续使用splitView,就将splitView的rootViewController和DetailViewController填充为所需内容,然后将Modal窗口动画退出。

Dave 没有错,但我会从这样一个角度来考虑问题:您正在剥夺用户的方向选择权;因为设计师假设某些配置更有效,从而删除标准选项(如支持的方向),只会惹恼一些用户。


谢谢Luke。这是一个很好的解释。我想到了另一个想法,如果我使用UIsplitviewcontroller并隐藏rootviewcontroller,使用detailview controller作为导航控制器呢?(因为我只有横向模式)这可行吗? - Nnp
我没有尝试过这个方法,但是我猜测它可能会给你带来一些意想不到的麻烦,比如调整细节框架的大小。(在横向模式下,detailView 有一个大约为350的x偏移量)如果你真的想用这种方式实现,我会把MGSplitViewController改造成适合你的需求。不过别忘了先阅读许可证。我的原始建议绝对是最轻松的解决方案。 - Luke Mcneice
作为附加问题:即使我将我的分割视图控制器设置为根视图,它只能在从主xib加载时才起作用。一旦我将其放入单独的xib中,将我的视图控制器(继承自UISplitViewController)与之关联并添加它,我得到的只是一个黑屏。放置断点后,我注意到分割控制器的内部视图从未被加载。似乎整个xib都没有被加载。但是没有错误。有什么想法如何将其放入自己的xib中吗?或者不可能吗? - Krumelur
innerViews?您是指rootViewController和detailViewController吗? - Luke Mcneice

2

我来试试,这对我有效。

1)在应用程序委托的didFinishLaunchingWithOptions方法中,将您的登录视图设置为根视图。

self.window.rootViewController = self.loginViewController;  

另外,按照模板的方式初始化分割视图(但不要添加到self.window中)。

MasterViewController *masterViewController = [[[MasterViewController alloc] initWithNibName:@"MasterViewController_iPad" bundle:nil] autorelease];
UINavigationController *masterNavigationController = [[[UINavigationController alloc] initWithRootViewController:masterViewController] autorelease];

    DetailViewController *detailViewController = [[[DetailViewController alloc] initWithNibName:@"DetailViewController_iPad" bundle:nil] autorelease];
    UINavigationController *detailNavigationController = [[[UINavigationController alloc] initWithRootViewController:detailViewController] autorelease];

    self.splitViewController = [[[UISplitViewController alloc] init] autorelease];
    self.splitViewController.delegate = detailViewController;
    self.splitViewController.viewControllers = [NSArray arrayWithObjects:masterNavigationController ,detailNavigationController, nil];

2) 在应用程序的委托中添加一个交换视图控制器,将根视图切换到分割视图控制器。

-(void)swapToViewControllers:(RootViewControllerType)viewType  
        self.window.rootViewController = self.splitViewController; 

3)在您的登录视图中调用swapToViewControllers函数。


在 RootViewControllerType 中需要给什么? - sairam

2

我通过在我的detailViewController中创建一个方法来完成它:

-(void)popHomeScreen:(BOOL)animated//OPENS THE HOMESCREEN IN A MODAL DISPLAY
{

  firstRun=NO;
    //myViewControllerForPopOver init here

    myViewControllerForPopOver.modalPresentationStyle = UIModalPresentationFullScreen;  


        myViewControllerForPopOver.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;//simple anime

    if (animated) [self presentModalViewController:myViewControllerForPopOver animated:YES];
        else [self presentModalViewController:myViewControllerForPopOver animated:NO];  
    }

然后在detailViewControllersViewDidAppear方法中调用它:

-(void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
if(firstRun)[self popHomeScreen:NO];
}

//YOU WILL ALSO NEED TO MAKE 'firstRun=YES' in viewDidLoad
//firstRun is a BOOL

关于根节点消失(留下一个大黑色空间)的问题,那是一个已知的bug。虽然我曾一度认为这是由于在它绘制之前/之时订购动画引起的。
此外,我发现如果我在分屏视图上弹出了一个全屏模态,然后快速地弹出另一个基于表单的模态(例如),则全屏模态无法正确绘制。
分屏视图就像你的婆婆,你不太喜欢它们,当你不得不使用它们时,你必须小心翼翼地绕过地雷。

你的评论“SplitViews 就像你的婆婆一样,…” 真是太棒了 :-) - Ekra

0

在Ryan CY的版本基础上进行了修改,使用了故事板(storyboard)。

Put this code to login controller.
1. Set storyboard id of UISplitViewController to SplitViewController;
2. Set UISplitViewController delegate and save instance

UISplitViewController* splitController = [self.storyboard instantiateViewControllerWithIdentifier:@"SplitViewController"];
UINavigationController* navigationController = [splitController.viewControllers lastObject];
splitController.delegate = (id)navigationController.topViewController;
3. Change rootViewController after login
self.view.window.rootViewController = splitController;


0

谢谢Dave。我的应用程序将更多地用于企业内部使用。(虽然我必须通过应用商店的审批过程,但它不会是通用的使用)。这样足够好吗? - Nnp
1
这取决于你希望应用程序被广泛分发的程度。我为客户开发了一些内部概念验证应用程序,这些应用程序部署在少数设备上,以展示给一些高管。通过这种方式,我们完全可以避免应用商店的流程。然而,如果您正在开发将在整个企业中分发的应用程序,您需要查看以下内容:http://developer.apple.com/programs/ios/enterprise/。 这是苹果企业开发者计划。我不太了解它,但我认为这可能是您想要的。 - Dave Klotz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接