首页 文章

在iOS8中使用UISplitViewController隐藏主视图控制器

提问于
浏览
38

我有一个iOS7应用程序,它基于Xcode主 - 详细信息模板,我移植到iOS8 . 一个变化很大的领域是 UISplitViewController .

在纵向模式下,如果用户点击详细视图控制器,则主视图控制器将被关闭:

enter image description here

如果用户点击一行,我还希望能够以编程方式隐藏主视图控制器 .

在iOS 7中,主视图控制器显示为弹出窗口,可以隐藏如下:

[self.masterPopoverController dismissPopoverAnimated:YES];

使用iOS 8,主服务器不再是popover,因此上述技术不起作用 .

我试图解雇主视图控制器:

self.dismissViewControllerAnimated(true, completion: nil)

或者告诉拆分视图控制器显示详细信息视图控制器:

self.splitViewController?.showDetailViewController(bookViewController!, sender: self)

但到目前为止还没有任何工作 . 有任何想法吗?

10 回答

  • 57

    按如下方式扩展UISplitViewController:

    extension UISplitViewController {
        func toggleMasterView() {
            let barButtonItem = self.displayModeButtonItem()
            UIApplication.sharedApplication().sendAction(barButtonItem.action, to: barButtonItem.target, from: nil, forEvent: nil)
        }
    }
    

    didSelectRowAtIndexPathprepareForSegue 中,执行以下操作:

    self.splitViewController?.toggleMasterView()
    

    这将使主视图平滑地滑动 .

    我有了使用this post中的displayModeButtonItem()的想法,我正在模拟每个this post点击它 .

    我对这个解决方案并不满意,因为它看起来像是一个黑客 . 但它运作良好,似乎没有其他选择 .

  • 0

    使用 preferredDisplayMode . 在 didSelectRowAtIndexPathprepareForSegue

    self.splitViewController?.preferredDisplayMode = .PrimaryHidden
    self.splitViewController?.preferredDisplayMode = .Automatic
    

    不幸的是,主视图突然消失而不是滑离,尽管文档说明:

    如果更改此属性的值会导致当前显示模式发生实际更改,则拆分视图控制器会对生成的更改进行动画处理 .

    希望有一个更好的方法来实现这个实际动画变化 .

  • 4

    通过在 MasterViewController- prepareForSegue:sender: 方法中添加以下代码,我能够在Xcode 6.3 Master-Detail Application(通用)项目中获得所需的行为:

    if view.traitCollection.userInterfaceIdiom == .Pad && splitViewController?.displayMode == .PrimaryOverlay {
        let animations: () -> Void = {
            self.splitViewController?.preferredDisplayMode = .PrimaryHidden
        }
        let completion: Bool -> Void = { _ in
            self.splitViewController?.preferredDisplayMode = .Automatic
        }
        UIView.animateWithDuration(0.3, animations: animations, completion: completion)
    }
    

    完整的 - prepareForSegue:sender: 实现应该如下所示:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == "showDetail" {
            if let indexPath = self.tableView.indexPathForSelectedRow() {
                let object = objects[indexPath.row] as! NSDate
                let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
                controller.detailItem = object
                controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
                controller.navigationItem.leftItemsSupplementBackButton = true
    
                if view.traitCollection.userInterfaceIdiom == .Pad && splitViewController?.displayMode == .PrimaryOverlay {
                    let animations: () -> Void = {
                        self.splitViewController?.preferredDisplayMode = .PrimaryHidden
                    }
                    let completion: Bool -> Void = { _ in
                        self.splitViewController?.preferredDisplayMode = .Automatic
                    }
                    UIView.animateWithDuration(0.3, animations: animations, completion: completion)
                }
            }
        }
    }
    

    在某些项目中,使用 traitCollection 也可能是 displayMode 的替代/补充 . 例如,以下代码也适用于Xcode 6.3 Master-Detail Application(通用)项目:

    let traits = view.traitCollection
    if traits.userInterfaceIdiom == .Pad && traits.horizontalSizeClass == .Regular {
        let animations: () -> Void = {
            self.splitViewController?.preferredDisplayMode = .PrimaryHidden
        }
        let completion: Bool -> Void = { _ in
            self.splitViewController?.preferredDisplayMode = .Automatic
        }
        UIView.animateWithDuration(0.3, animations: animations, completion: completion)
    }
    
  • 1

    下面的代码用动画隐藏主视图

    UIView.animateWithDuration(0.5) { () -> Void in
                self.splitViewController?.preferredDisplayMode = .PrimaryHidden
            }
    
  • 9

    只是改进了这里列出的答案,下面的代码对我来说正常工作,它也可以顺利处理动画:

    extension UISplitViewController {
        func toggleMasterView() {
            var nextDisplayMode: UISplitViewControllerDisplayMode
            switch(self.preferredDisplayMode){
            case .PrimaryHidden:
                nextDisplayMode = .AllVisible
            default:
                nextDisplayMode = .PrimaryHidden
            }
            UIView.animateWithDuration(0.5) { () -> Void in
                self.preferredDisplayMode = nextDisplayMode
            }
        }
    }
    

    然后,如上所述,您只需在View控制器的任何位置使用扩展功能

    self.splitViewController?.toggleMasterView()
    
  • 10

    修改上面的答案就是我在配置视图的详细视图控制器的方法中所需的全部内容:

    [self.splitViewController setPreferredDisplayMode:UISplitViewControllerDisplayModePrimaryHidden];
    

    当然它缺乏动画的优雅 .

  • 7

    尝试

    let svc = self.splitViewController
    svc.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden
    
  • 0

    我在Swift 1.2中的解决方案

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
        var screen = UIScreen.mainScreen().currentMode?.size.height
        if (UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad) || screen >= 2000 && UIDevice.currentDevice().orientation.isLandscape == true  && (UIDevice.currentDevice().userInterfaceIdiom == .Phone){
            performSegueWithIdentifier("showDetailParse", sender: nil)
            self.splitViewController?.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden
        } else if (UIDevice.currentDevice().userInterfaceIdiom == .Phone) {
            performSegueWithIdentifier("showParse", sender: nil)
        }
    }
    
  • 1

    为iPad添加这样的菜单按钮

    UIBarButtonItem *menuButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"burger_menu"]
                                                                           style:UIBarButtonItemStylePlain
                                                                          target:self.splitViewController.displayModeButtonItem.target
                                                                          action:self.splitViewController.displayModeButtonItem.action];
    [self.navigationItem setLeftBarButtonItem:menuButtonItem];
    

    这项工作非常适合横向和纵向模式 . 要以编程方式关闭popover vc,您只需要像这样强制执行按钮操作

    [self.splitViewController.displayModeButtonItem.target performSelector:appDelegate.splitViewController.displayModeButtonItem.action];
    
  • 0

    Swift 4更新:

    插入准备(对于segue:...

    if splitViewController?.displayMode == .primaryOverlay {
        let animations: () -> Void = {
            self.splitViewController?.preferredDisplayMode = .primaryHidden
        }
        let completion: (Bool) -> Void = { _ in
            self.splitViewController?.preferredDisplayMode = .automatic
        }
        UIView.animate(withDuration: 0.3, animations: animations, completion: completion)
    }
    

相关问题