iOS 13中,根据2019年WWDC的平台总览,苹果公司引入了一个新的默认卡片式呈现方式。为了强制全屏显示,您需要明确指定:
let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
有多种方法可以做到这一点,我认为每种方法可能适合一个项目但不适合另一个项目,所以我想把它们保存在这里,也许其他人会遇到不同的情况。
如果您有一个BaseViewController
,您可以覆盖present(_ viewControllerToPresent: animated flag: completion:)
方法。
class BaseViewController: UIViewController {
// ....
override func present(_ viewControllerToPresent: UIViewController,
animated flag: Bool,
completion: (() -> Void)? = nil) {
viewControllerToPresent.modalPresentationStyle = .fullScreen
super.present(viewControllerToPresent, animated: flag, completion: completion)
}
// ....
}
使用这种方式,您无需对任何present
调用进行任何更改,因为我们只是覆盖了present
方法。
extension UIViewController {
func presentInFullScreen(_ viewController: UIViewController,
animated: Bool,
completion: (() -> Void)? = nil) {
viewController.modalPresentationStyle = .fullScreen
present(viewController, animated: animated, completion: completion)
}
}
用法:
presentInFullScreen(viewController, animated: true)
let viewController = UIViewController()
viewController.modalPresentationStyle = .fullScreen
present(viewController, animated: true, completion: nil)
extension UIViewController {
static func swizzlePresent() {
let orginalSelector = #selector(present(_: animated: completion:))
let swizzledSelector = #selector(swizzledPresent)
guard let orginalMethod = class_getInstanceMethod(self, orginalSelector), let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) else{return}
let didAddMethod = class_addMethod(self,
orginalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self,
swizzledSelector,
method_getImplementation(orginalMethod),
method_getTypeEncoding(orginalMethod))
} else {
method_exchangeImplementations(orginalMethod, swizzledMethod)
}
}
@objc
private func swizzledPresent(_ viewControllerToPresent: UIViewController,
animated flag: Bool,
completion: (() -> Void)? = nil) {
if #available(iOS 13.0, *) {
if viewControllerToPresent.modalPresentationStyle == .automatic {
viewControllerToPresent.modalPresentationStyle = .fullScreen
}
}
swizzledPresent(viewControllerToPresent, animated: flag, completion: completion)
}
}
用法:
在你的AppDelegate
中的application(_ application: didFinishLaunchingWithOptions)
方法里添加这行代码:
UIViewController.swizzlePresent()
使用这种方式,您不需要对任何现有的调用进行任何更改,因为我们在运行时替换了当前方法的实现。
如果您想了解什么是swizzling,可以查看此链接:
https://nshipster.com/swift-objc-runtime/
.pageSheet
条件判断... 如果 viewControllerToPresent.modalPresentationStyle == .pageSheet || viewControllerToPresent.modalPresentationStyle == .automatic
,那么 viewControllerToPresent.modalPresentationStyle = .fullScreen
。 - Crash针对Objective-C用户
只需使用此代码即可
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
如果你想在iOS 13.0中特别添加它,那么使用以下方法:
if (@available(iOS 13.0, *)) {
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
} else {
// Fallback on earlier versions
}
NavigationController
中的 ViewController
,则必须将 NavigationController
设置为 .fullScreen
而不是VC。您可以像@davidbates一样这样做,或者以编程方式执行此操作(如@pascalbros)。对于UITabViewController
也适用相同的规则。关于NavigationController
的一个示例场景: //BaseNavigationController: UINavigationController {}
let baseNavigationController = storyboard!.instantiateViewController(withIdentifier: "BaseNavigationController")
var navigationController = UINavigationController(rootViewController: baseNavigationController)
navigationController.modalPresentationStyle = .fullScreen
navigationController.topViewController as? LoginViewController
self.present(navigationViewController, animated: true, completion: nil)
一句话概述:
modalPresentationStyle
需要在被呈现的导航控制器上设置。
iOS 13及以下版本中,使用
overCurrentContext
和navigationController
可以实现全屏。
测试代码
let controller = UIViewController()
let navigationController = UINavigationController(rootViewController: controller)
navigationController.modalPresentationStyle = .overCurrentContext
self.navigationController?.present(navigationController, animated: true, completion: nil)
modalPresentationStyle需要在navigationController上设置。
这对我起了作用
let vc = self.storyboard?.instantiateViewController(withIdentifier: "storyboardID_cameraview1") as! CameraViewController
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)`
我在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
}
UIViewController.preventPageSheetPresentation
),如果仍然发生,请找到实际问题,你在后台线程的某个地方调用了一些布局(我猜测是在网络请求完成时)。 - Maxime Ashurov适用于 iOS 13 和 Swift 5.x 的最新版本
let vc = ViewController(nibName: "ViewController", bundle: nil)
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: true, completion: nil)
isModalInPresentation
阻止滑动手势解除。有关更多详细信息,请参见我的博客文章:https://medium.com/@hacknicity/view-controller-presentation-changes-in-ios-13-ac8c901ebc4e - Geoff Hackworth.automatic
风格已经成为默认的风格,并且对于大多数视图控制器来说,它是.pageSheet
风格。然而,一些系统视图控制器可能会将其映射到不同的风格。 - Jakub TruhlářmodalPresentationStyle
添加到导航控制器而不是呈现的视图控制器。 - swiftcode