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?

modal behaviour

Merci

441
pascalbros 4 juin 2019 à 02:01

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:

enter image description here

    //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)
18
kuzdu 12 sept. 2019 à 19:22

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.

enter image description here

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"/>
0
Bangonkali 25 oct. 2019 à 15:01

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
 }
18
9to5ios 30 sept. 2019 à 07:36

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

8
Maxime Ashurov 2 oct. 2019 à 16:29

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)
-1
Master_Tushar 5 oct. 2019 à 11:22

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;
0
user1737746 9 oct. 2019 à 13:02

La solution la plus simple qui a fonctionné pour moi.

viewController.modalPresentationStyle = .fullScreen
0
Fahad Azeem 13 oct. 2019 à 07:54

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

0
Luca Iaco 9 oct. 2019 à 07:42

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:

fix_storyboard_presentation_default_behavior

59
davidbates 18 août 2019 à 17:32

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)
340
pascalbros 25 sept. 2019 à 21:15

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
0
Pramodya Abeysinghe 17 oct. 2019 à 05:39

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

enter image description here

10
Di Yawdie Dev 1 oct. 2019 à 03:40

Cela a fonctionné pour moi:

YourViewController.modalPresentationStyle = UIModalPresentationStyle.fullScreen

0
Dian 9 oct. 2019 à 23:02
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.

2
Mohit tomar 25 sept. 2019 à 10:33

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.

enter image description here

6
Mahesh Cheliya 19 oct. 2019 à 11:29
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.

0
Peter Tao 18 oct. 2019 à 06:04

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.
entrez la description de l'image ici

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/

34
Anush Shenoy 23 oct. 2019 à 07:45

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 .

enter image description here

95
Alessandro 10 juin 2019 à 16:27