Apresentação modal no iOS 13 em tela cheia

465

No iOS 13, há um novo comportamento para o controlador de exibição modal ao ser apresentado.

Agora, não está em tela cheia por padrão e, quando tento deslizar para baixo, o aplicativo simplesmente descarta o View Controller automaticamente.

Como posso evitar esse comportamento e voltar ao antigo modal em tela cheia vc?

comportamento modal

obrigado

pascalbros
fonte

Respostas:

622

Com o iOS 13, conforme declarado no Estado da União da Plataforma durante a WWDC 2019, a Apple apresentou uma nova apresentação de cartão padrão. Para forçar a tela cheia, você deve especificá-la explicitamente com:

let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
pascalbros
fonte
81
Eu diria que isso não vai ficar muito tempo como padrão. A fullScreenopção deve ser o padrão para impedir a quebra de alterações na interface do usuário.
Jakub Truhlář 5/06/19
17
Eu não vou contar com isso. No passado, a Apple frequentemente alterava os padrões, tornando-se ativos apenas quando você estava vinculando ao SDK atual. Vamos espero obter o comportamento de idade quando ligando contra as versões anteriores.
DrMickeyLauer 6/06/19
11
Posso confirmar que os aplicativos criados com o Xcode-10, executados no simulador do iOS 13, ainda usam a tela inteira como padrão. Como o @DrMickeyLauer disse, a construção com o Xcode 11 coloca o aplicativo no novo comportamento. Use isModalInPresentationpara impedir que o gesto de furto seja descartado. Ver meu blog para mais detalhes: medium.com/@hacknicity/...
Geoff Hackworth
5
Eu recomendo usar .fullScreen em vez de .overFullScreen. .fullScreen incêndios viewWillAppear e viewDidAppear, .overFullScreen não faz isso
Piterpan
5
O tempo passou e o .automaticestilo se estabeleceu como o padrão, que é o estilo (para a maioria dos controladores de exibição) .pageSheet. No entanto, alguns controladores de exibição do sistema podem mapeá-lo para um estilo diferente.
Jakub Truhlář
186

Eu adiciono uma informação que pode ser útil para alguém. Se você tiver alguma sequência de storyboard, para voltar ao estilo antigo, defina a propriedade kind como Present Modally e a propriedade Presentation em Full Screen .

insira a descrição da imagem aqui

Alessandro
fonte
2
Existe uma maneira no Interface Builder de definir isModalInPresentation?
Brad Thomas
Concordo com isso. Altere o valor da apresentação para a (s) visão (s) ofensiva (s) de nível mais alto.
David
Este é o que funcionou para mim porque eu tenho performSegue. Obrigado querida!
Blasanka 27/01
95

Eu tive esse problema na visualização inicial logo após a tela de lançamento. A correção para mim, já que eu não tinha uma sequência ou lógica definida, foi mudar a apresentação de automática para tela cheia, como mostrado aqui:

fix_storyboard_presentation_default_behavior

davidbates
fonte
2
Existe alguma maneira de fazer isso programaticamente para todas as visualizações, em vez de uma por uma através do storyboard?
The1993 30/09/19
@ The1993 Você encontrou alguma alternativa para isso?
Shobhit Puri
1
@ShobhitPuri Veja a primeira solução de Omreyh aqui stackoverflow.com/a/58255416/4323101 #
The1993
1
Uau, essa foi a resposta para meus problemas. Obrigado pela dica! Para outras pessoas que estudam isso também, essa é a correção para comportamentos estranhos após a reabertura do aplicativo em segundo plano. No meu aplicativo, a abertura em segundo plano sobrepunha minha tela inicial (controlador de exibição inicial) como um estilo de apresentação de cartão e, em seguida, todos os seguimentos daqui em diante se desvaneciam em vez de usar meu estilo segue definido. Seria bom se eu fechasse o aplicativo (toque duas vezes no botão inicial, deslize para cima e reabra), mas qualquer lançamento adicional causaria esse comportamento estranho. Obrigado novamente!
Justin
92

Existem várias maneiras de fazer isso, e acho que cada uma pode se encaixar em um projeto, mas não em outro, então pensei em mantê-las aqui, talvez outra pessoa vá para um caso diferente.

1- Substituir presente

Se você tiver um, BaseViewControllerpoderá substituir o present(_ viewControllerToPresent: animated flag: completion:)método.

class BaseViewController: UIViewController {

  // ....

  override func present(_ viewControllerToPresent: UIViewController,
                        animated flag: Bool,
                        completion: (() -> Void)? = nil) {
    viewControllerToPresent.modalPresentationStyle = .fullScreen
    super.present(viewControllerToPresent, animated: flag, completion: completion)
  }

  // ....
}

Dessa forma, você não precisa fazer nenhuma alteração em nenhuma presentchamada, pois acabamos de substituir o presentmétodo.

2- Uma extensão:

extension UIViewController {
  func presentInFullScreen(_ viewController: UIViewController,
                           animated: Bool,
                           completion: (() -> Void)? = nil) {
    viewController.modalPresentationStyle = .fullScreen
    present(viewController, animated: animated, completion: completion)
  }
}

Uso:

presentInFullScreen(viewController, animated: true)

3- Para um UIViewController

let viewController = UIViewController()
viewController.modalPresentationStyle = .fullScreen
present(viewController, animated: true, completion: nil)

4- Do Storyboard

Selecione uma segue e defina a apresentação como FullScreen.
insira a descrição da imagem aqui

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)
   }
}

Uso:
No seu AppDelegateinterior, application(_ application: didFinishLaunchingWithOptions)adicione esta linha:

UIViewController.swizzlePresent()

Dessa forma, você não precisa fazer nenhuma alteração em nenhuma chamada atual, pois estamos substituindo a implementação do método atual em tempo de execução.
Se você precisa saber o que é swizzling, pode verificar este link: https://nshipster.com/swift-objc-runtime/

Abedalkareem Omreyh
fonte
Eu tenho muitos viewControllers no meu projeto, mas não têm classe base, eu não quero swizzling você tem alguma solução para que, com mudanças mínimas no código
guru
Eu usei swizzling, mas adicionei .pageSheet à condição .... se viewControllerToPresent.modalPresentationStyle == .pageSheet || viewControllerToPresent.modalPresentationStyle == .automatic {viewControllerToPresent.modalPresentationStyle = .fullScreen}
Crash
barra de status é esconder quando eu adiciono solução aplicada no 1.
Ganesh Pawar
4
Swizzling é uma solução que funcionou muito bem por um tempo. No entanto, ao usar alguns sdks externos, como o FacebookLogin (5.8 até hoje) e o GoogleSignin, notei que esse método interrompe esses fluxos: temos uma tela branca no iPad. Provavelmente, isso se deve ao fato de eles usarem seu próprio método de swizzling
Tao-Nhan Nguyen
39

Eu usei swizzling para o 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)
    }
}

então coloque isso

UIViewController.preventPageSheetPresentation

algum lugar

por exemplo, no AppDelegate

func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]?) -> Bool {

    UIViewController.preventPageSheetPresentation
    // ...
    return true
}
Maxime Ashurov
fonte
3
Solução mais fácil se você tiver vários modais.
Raisal Calicut 29/10/19
meio em algum lugar, meio no qual arquivo ou onde no projeto como um todo
Yatendra
em algum lugar você, eu colocá-lo em AppDelegate static leté preguiçoso, você tem que lê-lo para deixá-lo ser calculado, var preguiçoso calculado apenas uma vez, eu usá-lo para ter garantia de que swizzling chamado uma vez
Maxime Ashurov
37

Para usuários do Objective-C

Basta usar este código

 [vc setModalPresentationStyle: UIModalPresentationFullScreen];

Ou se você quiser adicioná-lo em particular no iOS 13.0, use

 if (@available(iOS 13.0, *)) {
     [vc setModalPresentationStyle: UIModalPresentationFullScreen];
 } else {
     // Fallback on earlier versions
 }
9to5ios
fonte
2
Isso funciona em versão anterior do iOS também, mas a resposta é boa
Catalin
4
UIModalPresentationFullScreen funciona com iOS 3.2 ou superior. Portanto, não há necessidade de adicionar outra condição.
Flame3
2
Por algum motivo, no iOS 13.1.2, apenas nas classes Obj-c, isso não está funcionando e o modalPresentationStyle está exibindo apenas um pageSheet. Isso está acontecendo para mais alguém?
precisa saber é o seguinte
@ Sevy11 Não atualizei para o iOS 13.1.2, mas
estou
oi @ Sevy11 tenho atualizar meu iOS 13.1.2 e sua multa de trabalho, por favor, verifique no seu fim
9to5ios
36

Um forro:

modalPresentationStyledeve ser definido no navigationController que está sendo apresentado .


iOS 13 e inferior à versão iOS em tela cheia com overCurrentContexte navigationController

Código testado

let controller = UIViewController()
let navigationController = UINavigationController(rootViewController: controller)
navigationController.modalPresentationStyle = .overCurrentContext
self.navigationController?.present(navigationController, animated: true, completion: nil)

modalPresentationStyle requer que seja definido em navigationController .

Pratik Sodha
fonte
Um esclarecimento: apresentar um viewController a partir de um navigationController não precisa de modalPresentationStyle para ser definido no navigationController. Em vez disso, é definido no viewController sendo apresentado. No entanto, se você estiver apresentando um navigationController, a propriedade 'modalPresentationStyle' deve ser configurada no navigationController, não no viewController incorporado. Essa abordagem funciona no iOS 13.3, Xcode 11.3. Veja a resposta de Yogesh Bharate.
Womble 15/01
@Pratik Sodha. Alguma ajuda nisso? stackoverflow.com/questions/61429600/…
david
@Womble Qualquer ajuda neste stackoverflow.com/questions/61429600/…
david
25

Como dica: se você chamar de presente para um ViewControllerque está incorporado dentro de um, NavigationControllerprecisará definir o NavigationControllerpara .fullScreene não o VC.

Você pode fazer isso como @davidbates ou programaticamente (como @pascalbros).

Um cenário de exemplo:

insira a descrição da imagem aqui

    //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)
kuzdu
fonte
22

Eu precisava fazer as duas coisas:

  1. Definir estilo de apresentação como Tela inteira

    Tela cheia

  2. Definir barra superior como barra de navegação translúcida

Barra superior

vedrano
fonte
É uma suposição muito estranha que alguma opção no Simulated Metrics o ajude a mudar o estilo de apresentação
Alexander Kulabukhov 28/01
14

Alterar modalPresentationStyleantes de apresentar

vc.modalPresentationStyle = UIModalPresentationFullScreen;
MAMN84
fonte
13

Aqui está uma solução fácil sem codificar uma única linha.

  • Selecione Exibir controlador no Storyboard
  • Selecionar atributo Inspetor
  • Defina a apresentação "Automático" para "Tela cheia", conforme imagem abaixo

Essa alteração cria o comportamento do aplicativo para iPad conforme o esperado, caso contrário, a nova tela será exibida no centro da tela como um pop-up.

insira a descrição da imagem aqui

Mahesh Cheliya
fonte
Acho que o essencial aqui é que você fez isso no NavigationController, que é o que a imagem mostra, mas o texto não diz dessa maneira.
Andy Weinstein
1
verifique também se os itens subsequentes são "Mostrar" e não "Apresentar modalmente"
Andy Weinstein
Ok, então este parece funcionar para mim quando eu uso um controlador de barra de guias para controlar outras visualizações. No entanto, você precisa definir a Apresentação do 'Controlador de barras de guias' como Tela cheia, pois isso controla todas as outras visualizações.
Charlie
12

Se você possui um UITabController com telas com controladores de navegação incorporados, defina a Apresentação do UITabController como FullScreen, como mostra a figura abaixo

insira a descrição da imagem aqui

Di Nerd
fonte
12

Aqui está a solução para o Objective-C

UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
ViewController *vc = [storyBoard instantiateViewControllerWithIdentifier:@"ViewController"];

vc.modalPresentationStyle = UIModalPresentationFullScreen;

[self presentViewController:vc animated:YES completion:nil];
Prashanth Thota
fonte
10

Mais recente para iOS 13 e Swift 5.x

let vc = ViewController(nibName: "ViewController", bundle: nil)

vc.modalPresentationStyle = .fullScreen

self.present(vc, animated: true, completion: nil)
Rubaiyat Jahan Mumu
fonte
9

Aqui está minha versão da correção no ObjectiveC usando Categorias. Com essa abordagem, você terá o comportamento padrão do UIModalPresentationStyleFullScreen até que outra seja definida explicitamente.

#import "UIViewController+Presentation.h"
#import "objc/runtime.h"

@implementation UIViewController (Presentation)

- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
    [self setPrivateModalPresentationStyle:modalPresentationStyle];
}

-(UIModalPresentationStyle)modalPresentationStyle {
    UIModalPresentationStyle style = [self privateModalPresentationStyle];
    if (style == NSNotFound) {
        return UIModalPresentationFullScreen;
    }
    return style;
}

- (void)setPrivateModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
    NSNumber *styleNumber = [NSNumber numberWithInteger:modalPresentationStyle];
     objc_setAssociatedObject(self, @selector(privateModalPresentationStyle), styleNumber, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (UIModalPresentationStyle)privateModalPresentationStyle {
    NSNumber *styleNumber = objc_getAssociatedObject(self, @selector(privateModalPresentationStyle));
    if (styleNumber == nil) {
        return NSNotFound;
    }
    return styleNumber.integerValue;
}

@end
Alexander Kulabukhov
fonte
você tem o arquivo .h?
Pedro Góes
@ PedroGóes sim, mas consiste apenas na declaração de categoria: `` @interface UIViewController (Presentation) @end `` `
Alexander Kulabukhov
Use isso se você não quiser lidar com todos os controladores do seu storyboard! Economizador de tempo, obrigado!
AnthoPak
7

Todas as outras respostas são suficientes, mas para um projeto grande como o nosso e onde as navegações estão sendo feitas tanto em código quanto em storyboard, é uma tarefa bastante assustadora.

insira a descrição da imagem aqui

Para aqueles que estão usando ativamente o Storyboard. Este é o meu conselho: use Regex.

O seguinte formato não é bom para páginas em tela cheia:

<segue destination="Bof-iQ-svK" kind="presentation" identifier="importSystem" modalPresentationStyle="fullScreen" id="bfy-FP-mlc"/>

O seguinte formato é adequado para páginas em tela cheia:

<segue destination="7DQ-Kj-yFD" kind="presentation" identifier="defaultLandingToSystemInfo" modalPresentationStyle="fullScreen" id="Mjn-t2-yxe"/>

O seguinte regex compatível com o VS CODE converterá todas as páginas de estilo antigo em novas páginas de estilo. Pode ser necessário escapar de caracteres especiais se você estiver usando outros mecanismos de expressão regular / editores de texto.

Pesquisar Regex

<segue destination="(.*)"\s* kind="show" identifier="(.*)" id="(.*)"/>

Substituir Regex

<segue destination="$1" kind="presentation" identifier="$2" modalPresentationStyle="fullScreen" id="$3"/>
Bangonkali
fonte
4

Inicialmente, o valor padrão é fullscreenpara modalPresentationStyle, mas no iOS 13 suas alterações no UIModalPresentationStyle.automatic.

Se você deseja fazer o controlador de exibição em tela cheia, é necessário alterar modalPresentationStylepara fullScreen.

Consulte a UIModalPresentationStyle documentação da Apple para obter mais detalhes e consulte as diretrizes da interface humana da Apple para saber onde usar qual modalidade.

yo2bh
fonte
Esta é a resposta correta no iOS 13.3, Xcode 11.3, para situações em que você deseja apresentar um viewController a partir de um navigationController. Um modalPresentationStyle de .overFullScreen também funciona. No entanto, se você estiver apresentando um navigationController, precisará configurar 'modalPresentationStyle' no navigationController, não no viewController. Felicidades.
Womble 15/01
3

Você pode fazer isso facilmente Abra o seu storyboard como código-fonte e procure kind="presentation", em toda a tag seague com kind = presentation, adicione um atributo extramodalPresentationStyle="fullScreen"

amar
fonte
2
let Obj = MtViewController()
Obj.modalPresentationStyle = .overFullScreen
self.present(Obj, animated: true, completion: nil)

// se você deseja desativar o furto para dispensá-lo, adicione linha

Obj.isModalInPresentation = true

Consulte Apple Document para obter mais informações.

Mohit Tomar
fonte
2

Consegui isso usando o método swizzling (Swift 4.2):

Para criar uma extensão UIViewController da seguinte maneira

extension UIViewController {

    @objc private func swizzled_presentstyle(_ viewControllerToPresent: UIViewController, animated: Bool, completion: (() -> Void)?) {

        if #available(iOS 13.0, *) {
            if viewControllerToPresent.modalPresentationStyle == .automatic || viewControllerToPresent.modalPresentationStyle == .pageSheet {
                viewControllerToPresent.modalPresentationStyle = .fullScreen
            }
        }

        self.swizzled_presentstyle(viewControllerToPresent, animated: animated, completion: completion)
    }

     static func setPresentationStyle_fullScreen() {

        let instance: UIViewController = UIViewController()
        let aClass: AnyClass! = object_getClass(instance)

        let originalSelector = #selector(UIViewController.present(_:animated:completion:))
        let swizzledSelector = #selector(UIViewController.swizzled_presentstyle(_:animated:completion:))

        let originalMethod = class_getInstanceMethod(aClass, originalSelector)
        let swizzledMethod = class_getInstanceMethod(aClass, swizzledSelector)
        if let originalMethod = originalMethod, let swizzledMethod = swizzledMethod {
        method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }
}

e no AppDelegate, no aplicativo: didFinishLaunchingWithOptions: invoque o código swizzling chamando:

UIViewController.setPresentationStyle_fullScreen()
Sreeraj VR
fonte
1

Isso funcionou para mim:

yourViewController.modalPresentationStyle = UIModalPresentationStyle.fullScreen

Dian
fonte
3
Isso não adiciona nada a todas as outras respostas existentes.
rmaddy
1

Crie uma categoria para UIViewController (por exemplo, UIViewController + PresentationStyle). Adicione o seguinte código a ele.

 -(UIModalPresentationStyle)modalPresentationStyle{
     return UIModalPresentationStyleFullScreen;
}
Govind
fonte
isso irá interromper o UISearchController + acionar alguns travamentos difíceis de depurar
dklt 13/01
@dklt Essa é uma ótima observação. Portanto, definir a propriedade explicitamente resolverá o problema. Não há soluções mais simples se o UISearchController estiver usando.
Govind
0

uma abordagem alternativa é ter seu próprio componente de base do controlador de visualização em seu aplicativo e apenas implementar os inicializadores designados e necessários com uma configuração básica, algo como o seguinte:

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
    }
}

NOTA : Se o seu controlador de exibição estiver contido em um controlador de navegação que é realmente apresentado de forma modal, o controlador de navegação deve abordar o problema da mesma maneira (ou seja, ter seu componente personalizado do controlador de navegação personalizado da mesma maneira

Testado no Xcode 11.1 no iOS 13.1 e iOS 12.4

Espero que ajude

Luca Iaco
fonte
0

Eu tive esse problema com um vídeo que não apresenta mais a tela cheia. Adicionado esta linha, que salvou o dia :-)

videoController.modalPresentationStyle = UIModalPresentationFullScreen;
user1737746
fonte
2
Isso não adiciona nada a todas as outras respostas existentes.
rmaddy
0

A solução mais simples que funcionou para mim.

viewController.modalPresentationStyle = .fullScreen
Fahad Azeem
fonte
3
Isso não adiciona nada a todas as outras respostas existentes.
rmaddy
0

Se você estiver usando um UINavigationController e incorporar um ViewController como um controlador de exibição raiz, também poderá se deparar com o mesmo problema. Use o seguinte código para superar.

let vc = UIViewController()
let navController = UINavigationController(rootViewController: vc)
navController.modalPresentationStyle = .fullScreen
Pramodya Abeysinghe
fonte
0
class MyViewController: UIViewController {

    convenience init() {
        self.init(nibName:nil, bundle:nil)
        self.modalPresentationStyle = .fullScreen
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

Em vez de chamar self.modalPresentationStyle = .fullScreentodos os controladores de exibição, você pode subclassificar o UIViewController e apenas usá-lo em MyViewControllerqualquer lugar.

Peter Tao
fonte
-1

As respostas e sugestões acima estão corretas, abaixo está outra versão e maneira eficiente de usar programaticamente.

# 1 criou uma extensão UIView

# 2 criou um método ()

//#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)

  }
}

Invocando como abaixo

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)
Master_Tushar
fonte