使用 UIModalPresentationStyleCurrentContext 呈现视图控制器时的布局问题

Posted

技术标签:

【中文标题】使用 UIModalPresentationStyleCurrentContext 呈现视图控制器时的布局问题【英文标题】:Layout issues when presenting a view controller with UIModalPresentationStyleCurrentContext 【发布时间】:2015-03-24 20:29:51 【问题描述】:

我遇到了与 iPad 上的 UISplitViewController 和模态视图控制器有关的问题,因此我尝试在一个小项目中重现该问题,看看我是否能弄清楚发生了什么。不幸的是,问题似乎仍然存在,但我不知道为什么。

我在下面包含了一个非常小的、完整的 Swift 程序,它可以重现该问题。基本上,如果您在 iPad 上的新 Swift ios 项目中运行该代码,您将看到以下行为:

应用将以以下 UI 启动:

如果我点击显示,一个新的模态控制器将出现在拆分控制器的细节侧。如果我在该模态控制器上点击 Dismiss,我将返回相同的初始界面,一切都很好。

但是,如果我点击 Present,然后在出现的模态控制器上点击 Present(所以我在原始详细信息视图上有两个模态控制器),然后关闭最上面的一个,RightViewController 会占据整个屏幕,消除拆分视图控制器:

我整个下午都在为此苦苦思索。我有什么遗漏吗?

这里是示例应用程序的完整源代码:

import UIKit

class RightController: UIViewController 
    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) 
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        self.title = "Right"
    

    required init(coder aDecoder: NSCoder) 
      fatalError("init(coder:) has not been implemented")
    

    override func loadView() 
        super.loadView()

        let label = UILabel(frame: CGRect(x: 0, y: 100, width: 100, height: 20))
        label.text = "Top Left"
        self.view.addSubview(label)

        let presButton = UIBarButtonItem(title: "Present", style: .Plain, target: self, action: Selector("present:"))

        self.navigationItem.rightBarButtonItem = presButton
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Dismiss", style: .Plain, target: self, action: Selector("dismiss:"))
    

    func dismiss(sender: AnyObject) 
        self.dismissViewControllerAnimated(true, completion: nil)
    

    func present(sender: AnyObject) 
        let rc = RightController()
        let nav = UINavigationController(rootViewController: rc)
        nav.modalPresentationStyle = .CurrentContext
        self.presentViewController(nav, animated: true, completion: nil)
    


@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate 
    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool 
        let splitViewController = UISplitViewController()
        splitViewController.delegate = self

        let nav1 = UINavigationController(rootViewController: UIViewController())
        nav1.title = "Left"

        let nav2 = UINavigationController(rootViewController: RightController())

        splitViewController.viewControllers = [nav1, nav2]
        self.window!.rootViewController = splitViewController

        return true
    


extension AppDelegate: UISplitViewControllerDelegate 
    func splitViewController(svc: UISplitViewController, shouldHideViewController vc: UIViewController, inOrientation orientation: UIInterfaceOrientation) -> Bool 
        return false
    

编辑:循环浏览设备的方向会导致拆分视图控制器正确地重绘自身,至少在再次按下 Dismiss 之前。

编辑:如果我在 iOS 8 中使用新的 .OverCurrentContext 演示样式,我也可以让它工作。但是,我不能放弃与 iOS 7 的兼容性,所以我需要一个不同的解决方案。

【问题讨论】:

【参考方案1】:

我有一个可行的解决方案,虽然我会是第一个承认的,但它确实感觉有点老套。我认为您的问题很大一部分源于.CurrentContext 的更改,经过一些测试,我发现它在 iOS 7 和 8+ 上的功能不同。因此,如果您根据 iOS 版本选择合适的样式,一切正常:

var presStyle: UIModalPresentationStyle = (UIDevice.currentDevice().systemVersion as NSString).integerValue == 7 ? .CurrentContext : .OverCurrentContext
nav.modalPresentationStyle = presStyle

【讨论】:

这似乎有效!你是对的 - 看起来 .CurrentContext 的含义在操作系统之间发生了变化。我将在今天晚些时候对此进行深入测试,但现在它似乎确实解决了我的问题。谢谢! @Bill,很高兴它有效。是的,一个奇怪的变化。如果您对此还有任何问题,请告诉我。

以上是关于使用 UIModalPresentationStyleCurrentContext 呈现视图控制器时的布局问题的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)