在iOS 13中,模态视图控制器在呈现时有一个新的行为。
现在它不是全屏默认情况下,当我向下滑动时,应用会自动解除视图控制器。
我怎么能防止这种行为,并回到旧的全屏模态vc?
谢谢
在iOS 13中,模态视图控制器在呈现时有一个新的行为。
现在它不是全屏默认情况下,当我向下滑动时,应用会自动解除视图控制器。
我怎么能防止这种行为,并回到旧的全屏模态vc?
谢谢
当前回答
正如在2019年全球开发者大会上发布的平台国情咨文中所述,苹果在iOS 13中引入了新的默认卡显示方式。为了强制全屏,你必须明确地指定它:
let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
其他回答
快速的解决方案。上面已经有了很好的答案。我还添加了我的快速2点输入,在截图中显示。
如果你不使用导航控制器,那么从右菜单检查器将显示设置为全屏 如果你使用导航控制器,那么默认情况下它会显示全屏,你什么都不用做。
我添加的信息可能对某人有用。如果你有任何故事板segue,要回到旧的风格,你需要将kind属性设置为modal Present,并将Presentation属性设置为全屏。
对于Objective-C用户
只需使用这段代码
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
或者如果你想在iOS 13.0中添加它,那么使用
if (@available(iOS 13.0, *)) {
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
} else {
// Fallback on earlier versions
}
有多种方法可以做到这一点,我认为每一种方法都适合一个项目,但不适合另一个项目,所以我想我将它们保留在这里,也许其他人会处理不同的情况。
1-覆盖当前
如果你有一个BaseViewController,你可以重写present(_ viewcontrollertoppresent: 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方法。
2-扩展:
extension UIViewController {
func presentInFullScreen(_ viewController: UIViewController,
animated: Bool,
completion: (() -> Void)? = nil) {
viewController.modalPresentationStyle = .fullScreen
present(viewController, animated: animated, completion: completion)
}
}
用法:
presentInFullScreen(viewController, animated: true)
3-对于一个UIViewController
let viewController = UIViewController()
viewController.modalPresentationStyle = .fullScreen
present(viewController, animated: true, completion: nil)
4-从故事板
选择一个segue并将演示设置为FullScreen。
5 -狂饮
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: didFinishLaunchingWithOptions)中添加这一行:
UIViewController.swizzlePresent()
使用这种方式,您不需要对任何present调用做任何更改,因为我们正在运行时替换present方法实现。 如果你想知道什么是swizzling,你可以查看这个链接: https://nshipster.com/swift-objc-runtime/
提示:如果你调用present to一个嵌入在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)