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

Posted

技术标签:

【中文标题】如何使用 UISplitViewController 作为模态视图控制器?【英文标题】:How to use a UISplitViewController as a Modal View Controller? 【发布时间】:2011-01-19 19:36:58 【问题描述】:

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

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

【问题讨论】:

【参考方案1】:

像你们中的许多人一样,我需要一种“模态方式”来使用 UISplitViewController。这似乎是一个老问题,但我在 *** 中找到的所有内容充其量只是解释为什么当您尝试这样做时会发生问题(如上面接受的答案)或“hack-arounds”。

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

事实证明,有一种方法可以让每个人都开心(包括 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();
 

其中“窗口”是 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 不会 由系统自动恢复。

【讨论】:

【参考方案2】:

股票UISplitViewController 仅设计用作根视图控制器。展示一种模式违反了 Apple 人机界面指南,并且很有可能被 App Review 团队拒绝。此外,您可能会收到以下错误:

应用程序试图以模态方式呈现拆分视图控制器

【讨论】:

另一种方法是尝试使用售后市场的 splitview 控制器,例如 github.com/SlavaBushtruk/APSplitViewController【参考方案3】:

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

1/ 子类化 UIViewController 即。 @interface aVC: UIViewController

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

3/ 然后self.view = aSplitVC.view

毕竟,将 aVC 呈现为 modalViewController

【讨论】:

不适用于 Xcode 8、ios 8+ 有错误日志:“一个视图一次只能与一个视图控制器关联!”【参考方案4】:

我同意 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 中有一个工作返回按钮,该按钮以模态方式呈现在屏幕上。

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

[splitParentViewController dismissViewControllerAnimated:YES completion:nil];

【讨论】:

这里的基本思想运行良好,但如果其他东西没有保留它,ARC 可能会吃掉UISplitViewController。因此,如果您的视图的子视图在以这种方式呈现后消失了,请将其移至属性或其他东西中。【参考方案5】:

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

【讨论】:

【参考方案6】:

这个答案实际上并不正确,因为它自 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)

【讨论】:

以上是关于如何使用 UISplitViewController 作为模态视图控制器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用本机反应创建登录以及如何验证会话

如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]

如何使用 AngularJS 的 ng-model 创建一个数组以及如何使用 jquery 提交?

如何使用laravel保存所有行数据每个行名或相等

如何使用 Math.Net 连接矩阵。如何使用 Math.Net 调用特定的行或列?

WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?