我有一个iOS7应用程序,它基于Xcode主 - 详细信息模板,我正在移植到iOS8。一个变化很大的领域是UISplitViewController
。
在纵向模式下,如果用户点击详细视图控制器,则主视图控制器将被解除:
如果用户点击一行,我还希望能够以编程方式隐藏主视图控制器。
在iOS 7中,主视图控制器显示为弹出窗口,可以隐藏如下:
[self.masterPopoverController dismissPopoverAnimated:YES];
对于iOS 8,主人不再是弹出窗口,因此上述技术无效。
我试图解雇主视图控制器:
self.dismissViewControllerAnimated(true, completion: nil)
或告诉拆分视图控制器显示详细信息视图控制器:
self.splitViewController?.showDetailViewController(bookViewController!, sender: self)
但到目前为止还没有任何工作。有什么想法吗?
答案 0 :(得分:57)
按如下方式扩展UISplitViewController:
extension UISplitViewController {
func toggleMasterView() {
let barButtonItem = self.displayModeButtonItem()
UIApplication.sharedApplication().sendAction(barButtonItem.action, to: barButtonItem.target, from: nil, forEvent: nil)
}
}
在didSelectRowAtIndexPath
或prepareForSegue
中,执行以下操作:
self.splitViewController?.toggleMasterView()
这样可以顺畅地将主视图滑开。
我明白了使用this post中的displayModeButtonItem(),我正在模拟每this post点击它。
我对这个解决方案并不满意,因为它看起来像是一个黑客。但它运作良好,似乎没有其他选择。
答案 1 :(得分:10)
使用preferredDisplayMode
。在didSelectRowAtIndexPath
或prepareForSegue
:
self.splitViewController?.preferredDisplayMode = .PrimaryHidden
self.splitViewController?.preferredDisplayMode = .Automatic
不幸的是,主视图突然消失而不是滑离,尽管文档说明:
如果更改此属性的值会导致实际更改 在当前显示模式下,分割视图控制器动画显示 结果发生了变化。
希望有一种更好的方法可以实现动画的变化。
答案 2 :(得分:9)
通过在MasterViewController
{{1}中添加以下代码,我能够在 Xcode 6.3主 - 详细应用程序(通用)项目中获得所需的行为方法:
- 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)
}
实现应该如下所示:
- 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
的替代/补充。例如,以下代码也适用于 Xcode 6.3主 - 详细应用程序(通用)项目:
displayMode
答案 3 :(得分:7)
下面的代码用动画隐藏主视图
UIView.animateWithDuration(0.5) { () -> Void in
self.splitViewController?.preferredDisplayMode = .PrimaryHidden
}
答案 4 :(得分:5)
只是改进了这里列出的答案,以下代码对我来说正常工作,它也能顺利处理动画:
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()
答案 5 :(得分:1)
修改上面的答案就是我在配置视图的详细视图控制器的方法中所需的全部内容:
[self.splitViewController setPreferredDisplayMode:UISplitViewControllerDisplayModePrimaryHidden];
当然它缺乏动画的优雅。
答案 6 :(得分:1)
尝试
let svc = self.splitViewController svc.preferredDisplayMode = UISplitViewControllerDisplayMode.PrimaryHidden
答案 7 :(得分:1)
Swift 4更新:
将其插入prepare(for 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)
}
答案 8 :(得分: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)
}
}
答案 9 :(得分:0)
为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];
答案 10 :(得分:0)
与phatmann的方法非常相似,但是在Swift 5中更简单。而且从技术上讲,这不是“ hack”,因为这是iOS文档所建议的。
在您的prepareForSegue
或其他处理触摸的方法中,
let barButton = self.splitViewController?.displayModeButtonItem
_ = barButton?.target?.perform(barButton?.action)
根据Apple的规定,splitViewController
的{{1}}可以让您以适合设备方向的方式显示主视图控制器。也就是说,displayModeButtonItem
处于纵向模式。
所有要做的就是以编程方式按下按钮。或者,您可以像phatmann一样将其放在.preferHidden
的扩展名中。