如何使用UISplitViewController作为模态视图控制器?

我试图在我的iPad应用程序中显示一个UISplitViewController,将其显示为模态视图控制器。 我设法让它显示,但由于某种原因,模态视图左侧有一个间隙,状态栏的大小,当方向更改时也会保留。

替代文字

有人知道为什么会这样吗? 或者如果这是可能的话? 也许我只是在挖自己一个巨大的洞。

库存UISplitViewController作根视图控制器。 提出一个模态违反了Apple人机界面指南,很有可能被App Review团队拒绝。 此外,您可能会收到错误:

应用程序尝试以模态方式显示拆分视图控制器

对于你们许多人来说,我需要一种“模态方式”来使用UISplitViewController。 这似乎是一个老问题,但我在StackOverflow中发现的最多只是解释为什么当你试图这样做时(例如上面接受的答案)或’hack-arounds’时问题发生。

但是,有时更改大部分代码库并使UISplitViewController成为初始对象以使其function正常运行也不是很方便。

事实certificate,有一种方法可以让每个人都满意(包括Apple指南)。 我发现最好的解决方案是正常使用UISplitViewController,但是当需要显示/解除时,请使用以下方法:

 -(void)presentWithMasterViewController: (UIViewController *) thisMasterViewController andDetailViewController: (UIViewController *) thisDetailViewController completion:(void(^)(void))completion { masterViewController = thisMasterViewController; detailViewController = thisDetailViewController; [self setViewControllers:[NSArray arrayWithObjects:masterViewController, detailViewController, nil]]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; self.window.rootViewController = self; [self.window makeKeyAndVisible]; if(completion) completion(); } -(void)dismissViewControllerWithCompletion:(void (^)(void))completion { self.window = nil; masterViewController = nil; detailViewController = nil; if(completion) completion(); } 

其中“window”,是UISplitViewController子类的属性。 系统将负责其余的工作!

为了方便/参考,我将它作为UISplitViewController子类上传到gitHub:

ModalSplitViewController

– 如何使用示例 –

  mySplitViewController = [[ModalSplitViewController alloc] init]; mySplitViewController.delegate = self; [mySplitViewController presentWithMasterViewController:masterViewController andDetailViewController:detailViewController completion:nil]; // when done: [mySplitViewController dismissViewControllerWithCompletion:nil]; mySplitViewController = nil; 

旁注:我猜大多数混淆源于Apple文档中的UISplitView用法示例使用appDelegate中创建的窗口,以及大多数人对窗口概念不太熟悉的事实 – 因为我们通常不喜欢不需要(它们在StoryBoards或样板代码中创建一次)。

此外,如果您正在进行状态恢复,则不应忘记系统不会自动恢复以编程方式创建的UIViewControllers。

从技术上讲,这就是我所做的:

1 / Subclass一个UIViewController即。 @interface aVC:UIViewController

2 /在viewDidLoad中,设置一个splitViewController,即。 aSplitVC

3 /然后self.view = aSplitVC.view

毕竟,将aVC呈现为modalViewController

我同意Evan的说法,这对Apple来说略显偏色,但我能够通过以下解决方案完成此版本的工作:

 UISplitViewController *splitVC = [[UISplitViewController alloc] init]; splitVC.delegate = VC2; splitVC.viewControllers = [NSArray arrayWithObjects:navcon1, navcon2, nil]; UINavigationController *splitNavCon = [[UINavigationController alloc] init]; splitNavCon.modalTransitionStyle = UIModalTransitionStyleCoverVertical; [splitNavCon.view addSubview:splitVC.view]; VC2.splitParentViewController = splitNavCon; [self presentViewController:splitNavCon animated:YES completion:nil]; 

这让我在新的UISplitViewController中有一个工作后退按钮,它在屏幕上以模态方式呈现。

您会注意到我实际上将其父UINavigationController传递给VC2(UISplitViewController的委托)。 这是我发现我可以从VC2中解散UISplitViewController的最佳方式:

 [splitParentViewController dismissViewControllerAnimated:YES completion:nil]; 

我相信一个人可以做相反的事情:而不是自定义控制器呈现分割控制器,可以将分割控制器设置为故事板中的根窗口控制器,并且在其视图的顶部,您可以添加自定义控制器(即,登录屏幕) )并在需要时将其从屏幕上移除(例如removeFromSuperview)。

这个答案实际上并不正确,因为它自iOS8起不再有效,如果你需要支持甚至iOS7,你可以这样做,就像你实际上放置UIViewController一样,它有一个容器作为SplitView。

 let mdSplitView = self.storyboard?.instantiateViewControllerWithIdentifier("myDataSplitView") as! MyData_SplitVC self.addChildViewController(mdSplitView) mdSplitView.view.bounds = self.view.bounds self.view.addSubview(mdSplitView.view) mdSplitView.didMoveToParentViewController(self)