在iOS 13 Beta 1中,出现模态视图控制器时有新行为。现在默认情况下它不是全屏显示,当我尝试向下滑动时,该应用程序会自动关闭View Controller。
如何防止这种行为并回到旧的好全屏模式vc?
谢谢
1> pascalbros..:
如WWDC 2019期间平台联盟中所述,使用iOS 13,Apple引入了新的默认卡演示文稿。为了强制全屏,您必须使用以下命令明确指定它:
let vc = UIViewController()
vc.modalPresentatiOnStyle= .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
我会说这不会在默认情况下持续很长时间。“ fullScreen”选项应为默认设置,以防止破坏UI更改。
我不会指望这一点。过去,Apple经常更改默认设置,仅在与当前SDK链接后才激活默认设置。与以前的版本链接时,我们将“希望”获得旧的行为。
我可以确认在iOS 13模拟器上运行的Xcode-10构建的应用程序仍默认为全屏显示。正如@DrMickeyLauer所说,使用Xcode 11进行构建会使该应用程序采用新的行为。使用`isModalInPresentation`阻止取消滑动手势。有关更多详细信息,请参见我的博客文章:https://medium.com/@hacknicity/view-controller-presentation-changes-in-ios-13-ac8c901ebc4e
时间已经过去,.automatic样式已确定为默认样式,(对于大多数视图控制器而言)为.pageSheet样式。但是,某些系统视图控制器可能会将其映射为其他样式。
我建议使用.fullScreen而不是.overFullScreen。.fullScreen触发viewWillAppear和viewDidAppear,.overFullScreen则不执行
2> 小智..:
我添加了对某人可能有用的信息。如果您有任何故事板segue,那么要回到旧样式,需要将kind属性设置为Present Modally并将Presentation属性设置为Full Screen。
3> davidbates..:
在启动屏幕之后的初始视图中,我遇到了这个问题。因为没有定义顺序或逻辑,所以对我的解决方法是将演示文稿从自动切换到全屏,如下所示:
4> Abedalkareem..:
有多种方法可以做到这一点,我认为每个项目都可以适合一个项目,但又不适合另一个项目,所以我认为我会保留在这里,也许其他人会遇到不同的情况。
1-覆盖存在
如果您有一个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
方法。
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-从情节提要
选择一个序列并将演示文稿设置为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(_ application: didFinishLaunchingWithOptions)
添加以下行:
UIViewController.swizzlePresent()
使用这种方法,您不需要在任何当前调用上进行任何更改,因为我们正在运行时替换当前方法的实现。
如果您想知道什么在泛滥,可以查看以下链接:https :
//nshipster.com/swift-objc-runtime/
5> 9to5ios..:
对于Objective-C用户
只需使用此代码
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
或者,如果要在iOS 13.0中添加它,请使用
if (@available(iOS 13.0, *)) {
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
} else {
// Fallback on earlier versions
}
UIModalPresentationFullScreen可与iOS 3.2及更高版本一起使用。因此,如果没有其他条件,则无需添加。
这也适用于早期的ios版本,但是答案很好
由于某些原因,仅在iOS 13.1.2中,仅在Obj-c类中,此方法不起作用,而modalPresentationStyle仅显示pageSheet。这会发生在其他人身上吗?
6> kuzdu..:
提示:如果您对存在于ViewController
内嵌的的调用present ,则NavigationController
必须将设置为NavigationController
,.fullScreen
而不是VC。
您可以像@davidbates一样执行此操作,也可以通过编程方式(例如@pascalbros)来执行。
一个示例场景:
//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)
7> Maxime Ashur..:
我在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
}
8> Di Nerd..:
如果您的UITabController具有带嵌入式导航控制器的屏幕,则必须将UITabController Presentation设置为FullScreen,如下图所示
9> Mahesh Cheli..:
这是一个简单的解决方案,无需编码一行。
在情节提要中选择视图控制器
选择属性检查器
如下图所示,将演示文稿“自动”设置为“全屏”
此更改使iPad应用程序的行为符合预期,否则新屏幕将在弹出窗口的中央显示。
10> 小智..:
所有其他答案都足够了,但是对于像我们这样的大型项目来说,无论是在代码还是在情节提要中进行导航,这都是一项艰巨的任务。
对于那些正在积极使用Storyboard的人。这是我的建议:使用Regex。
以下格式不适用于全屏页面:
以下格式适合全屏页面:
以下与VS CODE兼容的正则表达式会将所有旧样式页面转换为新样式页面。如果您使用其他正则表达式引擎/文本编辑器,则可能需要转义特殊字符。
搜索正则表达式
替换正则表达式
11> 小智..:
这是Objective-C的解决方案
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ViewController *vc = [storyBoard instantiateViewControllerWithIdentifier:@"ViewController"];
vc.modalPresentatiOnStyle= UIModalPresentationFullScreen;
[self presentViewController:vc animated:YES completion:nil];