在iOS 13中,模态视图控制器在呈现时有一个新的行为。
现在它不是全屏默认情况下,当我向下滑动时,应用会自动解除视图控制器。
我怎么能防止这种行为,并回到旧的全屏模态vc?
谢谢
在iOS 13中,模态视图控制器在呈现时有一个新的行为。
现在它不是全屏默认情况下,当我向下滑动时,应用会自动解除视图控制器。
我怎么能防止这种行为,并回到旧的全屏模态vc?
谢谢
当前回答
另一种方法是在你的应用程序中拥有你自己的基本视图控制器组件,并通过一个基本的设置来实现指定的和必需的初始化器,如下所示:
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上测试
希望能有所帮助
其他回答
以上的答案和建议是正确的,下面是另一个版本,和有效的方法使用编程。
创建一个UIView扩展
创建一个方法()
//#1
extension UIViewController {
//#2
func presentLocal(_ viewControllerToPresent: UIViewController, animated flag:
Bool, completion: (() -> Void)? = nil) {
//Reusing below 2 lines :-)
viewControllerToPresent.modalPresentationStyle = .overCurrentContext
self.present(viewControllerToPresent, animated: flag, completion: completion)
}
}
调用如下所示
let vc = MyViewController()
let nc = UINavigationController(rootViewController: vc)
sourceView.presentLocal(nc, animated: true, completion: nil)
OR
let vc = MyViewController()
sourceView.presentLocal(vc, animated: true, completion: nil)
我需要同时做到这两点:
设置显示样式为全屏 设置顶部栏为半透明导航栏
我在启动屏幕后的初始视图中遇到了这个问题。修复我,因为我没有一个segue或逻辑定义是切换演示从自动到全屏如下所示:
有多种方法可以做到这一点,我认为每一种方法都适合一个项目,但不适合另一个项目,所以我想我将它们保留在这里,也许其他人会处理不同的情况。
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/
为UIViewController创建一个类别(比如UIViewController+PresentationStyle)。向其添加以下代码。
-(UIModalPresentationStyle)modalPresentationStyle{
return UIModalPresentationStyleFullScreen;
}