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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27243158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:30:59  来源:igfitidea点击:

Hiding the master view controller with UISplitViewController in iOS8

objective-cswiftios8uisplitviewcontroller

提问by ColinE

I have an iOS7 application, which was based on the Xcode master-detail template, that I am porting to iOS8. One area that has changed a lot is the UISplitViewController.

我有一个 iOS7 应用程序,它基于 Xcode 主从模板,我正在移植到 iOS8。发生了很大变化的一个领域是UISplitViewController.

When in portrait mode, if the user taps on the detail view controller, the master view controller is dismissed:

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

enter image description here

在此处输入图片说明

I would also like to be able to programmatically hide the master view controller if the user taps on a row.

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

In iOS 7, the master view controller was displayed as a pop-over, and could be hidden as follows:

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

[self.masterPopoverController dismissPopoverAnimated:YES];

With iOS 8, the master is no longer a popover, so the above technique will not work.

在 iOS 8 中,master 不再是 popover,因此上述技术将不起作用。

I've tried to dismiss the master view controller:

我试图关闭主视图控制器:

self.dismissViewControllerAnimated(true, completion: nil)

Or tell the split view controller to display the details view controller:

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

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

But nothing has worked so far. Any ideas?

但到目前为止没有任何效果。有任何想法吗?

回答by phatmann

Extend the UISplitViewController as follows:

扩展 UISplitViewController 如下:

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

In didSelectRowAtIndexPathor prepareForSegue, do the following:

didSelectRowAtIndexPath或 中prepareForSegue,执行以下操作:

self.splitViewController?.toggleMasterView()

This will smoothly slide the master view out of the way.

这将平滑地将主视图滑开。

I got the idea of using the displayModeButtonItem() from this postand I am simulating a tap on it per this post.

我使用displayModeButtonItem()从想法这篇文章,我每次上模拟水龙头这个职位

I am not really happy with this solution, since it seems like a hack. But it works well and there seems to be no alternative yet.

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

回答by Vinay Jain

Use preferredDisplayMode. In didSelectRowAtIndexPathor prepareForSegue:

使用preferredDisplayMode. 在didSelectRowAtIndexPathprepareForSegue

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

Unfortunately the master view abruptly disappears instead of sliding away, despite the documentation stating:

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

If changing the value of this property leads to an actual change in the current display mode, the split view controller animates the resulting change.

如果更改此属性的值导致当前显示模式的实际更改,则拆分视图控制器会为结果更改设置动画。

Hopefully there is a better way to do this that actually animates the change.

希望有一种更好的方法来做到这一点,实际上可以使更改动画化。

回答by Imanou Petit

I was able to have the desired behavior in a Xcode 6.3 Master-Detail Application (universal) projectby adding the following code in the MasterViewController's - prepareForSegue:sender:method:

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

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)
}

The complete - prepareForSegue:sender:implementation should look like this:

完整的- 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)
            }
        }
    }
}

Using traitCollectionmay also be an alternative/supplement to displayModein some projects. For example, the following code also works for a Xcode 6.3 Master-Detail Application (universal) project:

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

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)
}

回答by jithinroy

The code below hides the master view with animation

下面的代码隐藏了带有动画的主视图

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

回答by Santiago Bendavid

Just improving a little bit the answers listed here already, the following code is working properly for me, and it also handles the animation smoothly:

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

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
        }
    }
}

and then, as mentioned, you just use the extended function anywhere in your View controllers

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

self.splitViewController?.toggleMasterView()

回答by Andy G

Swift 4 update:

斯威夫特 4 更新:

Insert it into prepare(for segue: ...

将其插入准备(用于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)
}

回答by Tim

Modifying the answers above this is all I needed in a method of my detail view controller that configured the view:

在配置视图的详细视图控制器的方法中,我只需要修改上面的答案:

 [self.splitViewController setPreferredDisplayMode:UISplitViewControllerDisplayModePrimaryHidden];

Of course it lacks the grace of animation.

当然,它缺乏动画的优雅。

回答by daren

try

尝试

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

回答by coder1087

for iPad add Menu button like this

为 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];

This work great with both landscape and portrait mode. To programmatically close the popover vc you just need to force the button action like this

这适用于横向和纵向模式。要以编程方式关闭 popover vc,您只需要像这样强制按钮操作

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

回答by Alexander Khitev

My solution in the Swift 1.2

我在 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)
    }
}