Dans iOS 13 Beta 1, il existe un nouveau comportement pour le contrôleur de vue modale lors de sa présentation. Maintenant, ce n'est pas plein écran par défaut et lorsque j'essaie de glisser vers le bas, l'application ferme simplement le contrôleur de vue automatiquement.
Comment puis-je empêcher ce comportement et revenir à l'ancien bon modal vc plein écran?
Merci
18 réponses
À titre indicatif: si vous appelez present à un ViewController
qui est intégré dans un NavigationController
, vous devez définir le NavigationController
sur .fullScreen
et non le VC.
Vous pouvez le faire comme @davidbates ou vous le faites par programme (comme @pascalbros).
Un exemple de scénario:
//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)
Toutes les autres réponses sont suffisantes, mais pour un grand projet comme le nôtre et où les navigations sont effectuées à la fois dans le code et le storyboard, c'est une tâche assez intimidante.
Pour ceux qui utilisent activement Storyboard. Voici mon conseil: utilisez Regex.
Le format suivant n'est pas adapté aux pages plein écran:
<segue destination="Bof-iQ-svK" kind="presentation" identifier="importSystem" modalPresentationStyle="fullScreen" id="bfy-FP-mlc"/>
Le format suivant convient aux pages plein écran:
<segue destination="7DQ-Kj-yFD" kind="presentation" identifier="defaultLandingToSystemInfo" modalPresentationStyle="fullScreen" id="Mjn-t2-yxe"/>
Le regex suivant compatible avec VS CODE convertira toutes les pages de l'ancien style en nouvelles pages de style. Vous devrez peut-être échapper des caractères spéciaux si vous utilisez d'autres moteurs / éditeurs de texte regex.
Rechercher Regex
<segue destination="(.*)"\s* kind="show" identifier="(.*)" id="(.*)"/>
Remplacer Regex
<segue destination="$1" kind="presentation" identifier="$2" modalPresentationStyle="fullScreen" id="$3"/>
Pour les utilisateurs d'Objective-C
Utilisez simplement ce code
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
Ou si vous souhaitez l'ajouter en particulier dans iOS 13.0, utilisez
if (@available(iOS 13.0, *)) {
[vc setModalPresentationStyle: UIModalPresentationFullScreen];
} else {
// Fallback on earlier versions
}
J'ai utilisé swizzling pour ios 13
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)
}
}
Puis mettez ça
UIViewController.preventPageSheetPresentation
Quelque part
Les réponses et suggestions ci-dessus sont exactes, voici une autre version et une manière efficace d'utiliser par programmation.
# 1 a créé une extension UIView
# 2 a créé une méthode ()
//#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)
}
}
Appel comme ci-dessous
let vc = MyViewController()
let nc = UINavigationController(rootViewController: vc)
sourceView.presentLocal(nc, animated: true, completion: nil)
OU
let vc = MyViewController()
sourceView.presentLocal(vc, animated: true, completion: nil)
J'ai eu ce problème avec une vidéo ne présentant plus le plein écran. Ajout de cette ligne, qui a sauvé la journée :-)
videoController.modalPresentationStyle = UIModalPresentationFullScreen;
La solution la plus simple qui a fonctionné pour moi.
viewController.modalPresentationStyle = .fullScreen
Une autre approche consiste à avoir votre propre composant de base viewcontroller dans votre application, et à simplement implémenter les initialiseurs désignés et requis avec une configuration de base, quelque chose comme ceci:
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
}
}
REMARQUE : si votre contrôleur de vue est contenu dans un contrôleur de navigation qui est en fait présenté de manière modale, alors le contrôleur de navigation doit aborder le problème de la même manière (ce qui signifie, avoir votre composant de contrôleur de navigation personnalisé personnalisé de la même manière). façon
Testé sur Xcode 11.1 sur iOS 13.1 et iOS 12.4
J'espère que cela aide
J'ai eu ce problème sur la vue initiale juste après l'écran de lancement. Le correctif pour moi puisque je n'avais pas de séquence ou de logique définie était de basculer la présentation de l'automatique au plein écran comme indiqué ici:
Avec iOS 13, comme indiqué dans l 'État des plates-formes de l'Union pendant la WWDC 2019, Apple a introduit une nouvelle présentation de carte par défaut. Pour forcer le plein écran, vous devez le spécifier explicitement avec:
let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
Si vous utilisez un UINavigationController et intégrez un ViewController en tant que contrôleur de vue racine, vous rencontrerez également le même problème. Utilisez le code suivant pour surmonter.
let vc = UIViewController()
let navController = UINavigationController(rootViewController: vc)
navController.modalPresentationStyle = .fullScreen
Si vous avez un UITabbarController avec des écrans avec des contrôleurs de navigation intégrés, vous devez définir la Présentation de l'UITabbarController sur FullScreen comme indiqué sur l'image ci-dessous
Cela a fonctionné pour moi:
YourViewController.modalPresentationStyle = UIModalPresentationStyle.fullScreen
let Obj = MtViewController()
Obj.modalPresentationStyle = .overFullScreen
self.present(Obj, animated: true, completion: nil)
// si vous souhaitez désactiver le glissement pour le supprimer, ajoutez une ligne
Obj.isModalInPresentation = true
Consultez le document Apple pour plus d'informations.
Voici une solution simple sans coder une seule ligne.
- Sélectionnez Afficher le contrôleur dans le Storyboard
- Sélectionner un inspecteur d'attributs
- Réglez la présentation "Automatique" sur "Plein écran" comme sur l'image ci-dessous
Cette modification rend le comportement de l'application iPad comme prévu, sinon le nouvel écran s'affiche au centre de l'écran sous forme de popup.
class MyViewController: UIViewController {
convenience init() {
self.init(nibName:nil, bundle:nil)
self.modalPresentationStyle = .fullScreen
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Plutôt que d'appeler self.modalPresentationStyle = .fullScreen
pour chaque contrôleur de vue, vous pouvez sous-classer UIViewController et simplement utiliser MyViewController
partout.
Il y a plusieurs façons de le faire, et je pense que chacune pourrait convenir à un projet mais pas à un autre, alors j'ai pensé que je les garderais ici, peut-être que quelqu'un d'autre courrait vers un cas différent.
1- Remplacer présent
Si vous avez un BaseViewController
, vous pouvez remplacer la méthode 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)
}
// ....
}
En utilisant cette méthode, vous n'avez pas besoin de faire de changement sur aucun appel present
, car nous venons de remplacer la méthode present
.
2- Une extension:
extension UIViewController {
func presentInFullScreen(_ viewController: UIViewController,
animated: Bool,
completion: (() -> Void)? = nil) {
viewController.modalPresentationStyle = .fullScreen
present(viewController, animated: animated, completion: completion)
}
}
Usage:
presentInFullScreen(viewController, animated: true)
3- Pour un UIViewController
let viewController = UIViewController()
viewController.modalPresentationStyle = .fullScreen
present(viewController, animated: true, completion: nil)
4- Depuis Storyboard
Sélectionnez une séquence et définissez la présentation sur FullScreen
.
5- Swizzling
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)
}
}
Utilisation:
Dans votre AppDelegate
inside application(_ application: didFinishLaunchingWithOptions)
, ajoutez cette ligne:
UIViewController.swizzlePresent()
En utilisant cette méthode, vous n'avez pas besoin de faire de changement sur aucun appel actuel, car nous remplaçons l'implémentation de la méthode actuelle dans le runtime. Si vous avez besoin de savoir ce qui bouge, vous pouvez consulter ce lien: https://nshipster.com/swift-objc-runtime/
J'ajoute une information qui pourrait être utile à quelqu'un. Si vous avez une séquence de storyboard, pour revenir à l'ancien style, vous devez définir la propriété kind sur Present Modally et la propriété Presentation à Plein écran .
Questions connexes
De nouvelles questions
ios
iOS est le système d'exploitation mobile fonctionnant sur Apple iPhone, iPod touch et iPad. Utilisez cette balise [ios] pour les questions liées à la programmation sur la plate-forme iOS. Utilisez les balises associées [objective-c] et [swift] pour les problèmes spécifiques à ces langages de programmation.