在iOS 13中,模态视图控制器在呈现时有一个新的行为。

现在它不是全屏默认情况下,当我向下滑动时,应用会自动解除视图控制器。

我怎么能防止这种行为,并回到旧的全屏模态vc?

谢谢


当前回答

如果你有一个带有嵌入式导航控制器的UITabController,你必须将UITabController的显示设置为全屏,如下图所示

其他回答

如果你有一个带有嵌入式导航控制器的UITabController,你必须将UITabController的显示设置为全屏,如下图所示

另一种方法是在你的应用程序中拥有你自己的基本视图控制器组件,并通过一个基本的设置来实现指定的和必需的初始化器,如下所示:

class MyBaseViewController: UIViewController {

//MARK: Initialisers

/// Alternative initializer which allows you to set the modal presentation syle
/// - Parameter modalStyle: the presentation style to be used
init(with modalStyle:UIModalPresentationStyle) {
    super.init(nibName: nil, bundle: nil)
    self.setup(modalStyle: modalStyle)
}

override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
    // default modal presentation style as fullscreen
    self.setup(modalStyle: .fullScreen)
}

required init?(coder: NSCoder) {
    super.init(coder: coder)
    // default modal presentation style as fullscreen
    self.setup(modalStyle: .fullScreen)
}

//MARK: Private

/// Setup the view
///
/// - Parameter modalStyle: indicates which modal presentation style to be used
/// - Parameter modalPresentation: default true, it prevent modally presented view to be dismissible with the default swipe gesture
private func setup(modalStyle:UIModalPresentationStyle, modalPresentation:Bool = true){
    if #available(iOS 13, *) {
        self.modalPresentationStyle = modalStyle
        self.isModalInPresentation = modalPresentation
    }
}

注意:如果你的视图控制器包含在一个以模态方式呈现的导航控制器中,那么导航控制器应该以同样的方式处理这个问题(也就是说,用同样的方式定制你的自定义导航控制器组件)

在Xcode 11.1、iOS 13.1和iOS 12.4上测试

希望能有所帮助

我在ios 13中使用了swizzling

import Foundation
import UIKit

private func _swizzling(forClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) {
    if let originalMethod = class_getInstanceMethod(forClass, originalSelector),
       let swizzledMethod = class_getInstanceMethod(forClass, swizzledSelector) {
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }
}

extension UIViewController {

    static let preventPageSheetPresentation: Void = {
        if #available(iOS 13, *) {
            _swizzling(forClass: UIViewController.self,
                       originalSelector: #selector(present(_: animated: completion:)),
                       swizzledSelector: #selector(_swizzledPresent(_: animated: completion:)))
        }
    }()

    @available(iOS 13.0, *)
    @objc private func _swizzledPresent(_ viewControllerToPresent: UIViewController,
                                        animated flag: Bool,
                                        completion: (() -> Void)? = nil) {
        if viewControllerToPresent.modalPresentationStyle == .pageSheet
                   || viewControllerToPresent.modalPresentationStyle == .automatic {
            viewControllerToPresent.modalPresentationStyle = .fullScreen
        }
        _swizzledPresent(viewControllerToPresent, animated: flag, completion: completion)
    }
}

然后放这个

UIViewController.preventPageSheetPresentation

的某个地方

例如在AppDelegate中

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {

    UIViewController.preventPageSheetPresentation
    // ...
    return true
}

一个衬套:

modalPresentationStyle需要在正在呈现的navigationController上设置。


iOS 13及以下的iOS版本fullScreen with overCurrentContext和 导航控制器

经过测试的代码

let controller = UIViewController()
let navigationController = UINavigationController(rootViewController: controller)
navigationController.modalPresentationStyle = .overCurrentContext
self.navigationController?.present(navigationController, animated: true, completion: nil)

modalPresentationStyle需要设置在navigationController。

这里有一个简单的解决方案,无需编写任何代码。

在故事板中选择视图控制器 选择属性检查器 按照下图将显示“自动”设置为“全屏”

这一变化使iPad应用程序的行为符合预期,否则新屏幕将以弹出窗口的形式显示在屏幕中央。