Представление модального окна в полноэкранном режиме iOS 13

В iOS 13 появилось новое поведение для контроллера модального представления при его представлении.

Теперь по умолчанию он не полноэкранный, и когда я пытаюсь скользить вниз, приложение просто автоматически закрывает View Controller.

Как я могу предотвратить такое поведение и вернуться к старому полноэкранному модальному vc?

модальное поведение

Спасибо


person pascalbros    schedule 03.06.2019    source источник


Ответы (26)


С iOS 13, как указано в состоянии платформ Союза во время WWDC В 2019 году Apple представила новую презентацию карты по умолчанию. Чтобы заставить полноэкранный режим, вы должны явно указать это с помощью:

let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)
person pascalbros    schedule 03.06.2019
comment
Я бы сказал, что это не продлится долго по умолчанию. Параметр fullScreen должен быть установлен по умолчанию, чтобы предотвратить нарушение пользовательского интерфейса. - person Jakub Truhlář; 05.06.2019
comment
Я не буду на это рассчитывать. В прошлом Apple часто меняла настройки по умолчанию, становясь активными только после подключения к текущему SDK. Мы надеемся получить старое поведение при связывании с предыдущими версиями. - person DrMickeyLauer; 06.06.2019
comment
Я могу подтвердить, что приложения, созданные на Xcode-10, запускаемые на симуляторе iOS 13, по-прежнему работают в полноэкранном режиме. Как сказал @DrMickeyLauer, при сборке с Xcode 11 приложение выбирает новое поведение. Используйте isModalInPresentation, чтобы заблокировать жест смахивания. Дополнительную информацию см. В моем сообщении в блоге: medium.com / @ hacknicity / - person Geoff Hackworth; 08.06.2019
comment
В классе .compact горизонтального размера представление .fullScreen не действует точно так же, как .formSheet в iOS 12. Вы должны использовать режим .overFullScreen, чтобы полностью воспроизвести старое поведение. - person Iliyan Kafedzhiev; 21.09.2019
comment
Я рекомендую использовать .fullScreen вместо .overFullScreen. .fullScreen запускает viewWillAppear и viewDidAppear, .overFullScreen этого не делает - person PiterPan; 25.09.2019
comment
Прошло время, и стиль .automatic утвердился в качестве стиля по умолчанию, который (для большинства контроллеров представлений) является стилем .pageSheet. Однако некоторые контроллеры системного представления могут отображать его в другом стиле. - person Jakub Truhlář; 29.09.2019
comment
Не повезло с этим с MFMessageComposeViewController. Устанавливается на полноэкранный режим, но остается в новом формате карты. - person Luke Irvin; 22.01.2020
comment
Как бы вы закрыли эту ВК? - person JAWS007; 07.03.2020
comment
Имейте в виду, что если вы используете контроллер навигации, modalPresentationStyle должен быть добавлен к контроллеру навигации, не представленный контроллер представления. - person swiftcode; 16.06.2020
comment
@ JAWS007 Вы можете позвонить dismiss(animated: completion:) либо из виртуального канала, который его представляет, либо из виртуального канала, который был представлен. Он удалит самый верхний VC из стека навигации. - person swiftcode; 16.06.2020

Добавляю информацию, которая может быть кому-то полезна. Если у вас есть какая-либо раскадровка, чтобы вернуться к старому стилю, вам необходимо установить для свойства kind значение Present Modally и свойство Presentation. на Во весь экран.

введите описание изображения здесь

person Alessandro    schedule 10.06.2019
comment
Есть ли способ в Интерфейсном Разработчике установить isModalInPresentation? - person Brad Thomas; 01.10.2019

У меня возникла эта проблема на начальном экране сразу после экрана запуска. Исправление для меня, поскольку у меня не было определенного перехода или логики, заключалось в переключении презентации с автоматического на полноэкранный режим, как показано здесь:

fix_storyboard_presentation_default_behavior

person davidbates    schedule 18.08.2019
comment
Есть ли способ сделать это программно для всех представлений вместо одного за другим через раскадровку? - person The1993; 30.09.2019
comment
@ShobhitPuri Взгляните на первое решение Омрейха здесь stackoverflow.com/a/58255416/4323101 - person The1993; 10.12.2019
comment
Вау, это был ответ на мои проблемы. Спасибо за совет! Для всех, кто также занимается этим, это исправление странного поведения после повторного открытия приложения в фоновом режиме. В моем приложении открытие из фона наложило бы мой экран-заставку (начальный контроллер представления) в качестве стиля представления карты, а затем любые переходы отсюда и далее будут плавно затухать вместо использования моего определенного стиля перехода. Было бы хорошо, если бы я закрыл приложение (дважды нажмите кнопку «Домой» и проведите пальцем вверх, а затем снова откройте), но любые дополнительные запуски вызовут это странное поведение. Спасибо еще раз! - person Justin; 11.01.2020

Есть несколько способов сделать это, и я думаю, что каждый из них может подойти для одного проекта, но не подходит для другого, поэтому я подумал, что оставлю их здесь, возможно, кто-то другой перейдет к другому делу.

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

Использование:
В вашем AppDelegate внутри application(_ application: didFinishLaunchingWithOptions) добавьте эту строку:

UIViewController.swizzlePresent()

Используя этот способ, вам не нужно вносить какие-либо изменения в какой-либо текущий вызов, поскольку мы заменяем текущую реализацию метода во время выполнения.
Если вам нужно знать, что такое swizzling, вы можете проверить эту ссылку: https://nshipster.com/swift-objc-runtime/

person Abedalkareem Omreyh    schedule 06.10.2019
comment
В моем проекте много viewControllers, но у меня нет базового класса, я не хочу swizzling, есть ли у вас какое-либо решение для этого с минимальными изменениями в коде - person guru; 08.11.2019
comment
Я использовал swizzling, но добавил .pageSheet в условие .... if viewControllerToPresent.modalPresentationStyle == .pageSheet || viewControllerToPresent.modalPresentationStyle == .automatic {viewControllerToPresent.modalPresentationStyle = .fullScreen} - person Crash; 15.11.2019
comment
Строка состояния скрывается, когда я добавляю прикладное решение №1. - person Ganesh Pawar; 21.11.2019
comment
Swizzling - это решение, которое какое-то время отлично работало. Однако при использовании некоторых внешних SDK, таких как FacebookLogin (на сегодняшний день 5.8) и GoogleSignin, я заметил, что этот метод нарушает эти потоки: мы получаем белый экран на iPad. Вероятно, это связано с тем, что они используют свой собственный метод обжаривания. - person Tao-Nhan Nguyen; 21.12.2019

Для пользователей Objective-C

Просто используйте этот код

 [vc setModalPresentationStyle: UIModalPresentationFullScreen];

Или, если вы хотите добавить его в iOS 13.0, используйте

 if (@available(iOS 13.0, *)) {
     [vc setModalPresentationStyle: UIModalPresentationFullScreen];
 } else {
     // Fallback on earlier versions
 }
person 9to5ios    schedule 24.09.2019
comment
UIModalPresentationFullScreen работает с iOS 3.2+. Поэтому не нужно добавлять условие if else. - person flame3; 28.09.2019
comment
По какой-то причине в iOS 13.1.2 только в классах Obj-c это не работает, а modalPresentationStyle отображает только pageSheet. Это происходит с кем-нибудь еще? - person Sevy11; 04.10.2019
comment
@ Sevy11 Я не обновлялся до iOS 13.1.2, но работает нормально на 13.1 - person 9to5ios; 04.10.2019

Я использовал swizzling для 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)
    }
}

тогда положи это

UIViewController.preventPageSheetPresentation

где-то

например в AppDelegate

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

    UIViewController.preventPageSheetPresentation
    // ...
    return true
}
person Maxime Ashurov    schedule 02.10.2019
comment
Используя это, мы получаем следующую ошибку для некоторых устройств Fatal Exception: NSInternalInconsistencyException Модификации механизма компоновки не должны выполняться из фонового потока после того, как к нему был осуществлен доступ из основного потока. - person krishnan; 17.11.2020
comment
это странно, оформляйте заказ, если это происходит без swizzling (прокомментируйте эту строку UIViewController.preventPageSheetPresentation), если это все еще происходит, найдите фактическую проблему, вы вызываете какой-то макет где-то в фоновом потоке (я думаю, в завершении сетевого запроса) - person Maxime Ashurov; 19.11.2020


Один лайнер:

modalPresentationStyle необходимо установить в navigationController , который сейчас представлен.


iOS 13 и ниже версии iOS полноэкранный режим с overCurrentContext и navigationController

Протестированный код

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

modalPresentationStyle необходимо установить в navigationController.

person Pratik Sodha    schedule 27.11.2019
comment
Уточнение: представление viewController из navigationController не требует установки modalPresentationStyle в navigationController. Вместо этого он устанавливается для представленного viewController. Однако, если вы представляете NavigationController, тогда свойство modalPresentationStyle должно быть установлено для navigationController, а не для встроенного viewController. Этот подход работает iOS 13.3, Xcode 11.3. См. Ответ Йогеша Бхарате. - person Womble; 16.01.2020

В качестве подсказки: если вы вызываете Present для ViewController, который встроен в NavigationController, вы должны установить NavigationController в .fullScreen, а не VC.

Вы можете сделать это как @davidbates или сделать это программно (например, @pascalbros).

То же самое и с UITabViewController

Пример сценария для NavigationController:

введите описание изображения здесь

    //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)
person kuzdu    schedule 10.09.2019
comment
Это действительно полезный момент. Действительно легко забыть и свести с ума (я так и сделал). Спасибо - person rmvz3; 16.02.2021

Мне нужно было сделать и то, и другое:

  1. Установить стиль презентации как полноэкранный

    Полный экран

  2. Установить верхнюю панель как полупрозрачную панель навигации

Верхняя панель

person vedrano    schedule 27.11.2019
comment
Очень странное предположение, что некоторые опции в Simulated Metrics помогают изменить стиль презентации. - person Alexander Kulabukhov; 28.01.2020
comment
@AlexanderKulabukhov нет. Это чисто смоделировано. - person Kyle Browning; 27.08.2020

Последняя версия для iOS 13 и Swift 5.x

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

vc.modalPresentationStyle = .fullScreen

self.present(vc, animated: true, completion: nil)
person Rubaiyat Jahan Mumu    schedule 06.04.2020

Быстрое решение. Выше уже есть действительно отличные ответы. Я также добавляю свой быстрый ввод двух точек, который представлен на скриншоте.

  1. Если вы не используете Navigation Controller, то с Right Menu Inspector установите для параметра «Презентация» значение Full Screen.

  2. Если вы используете Navigation Controller, то по умолчанию он будет отображаться в полноэкранном режиме, вам не нужно ничего делать.

введите описание изображения здесь

person Rana Ijaz    schedule 09.07.2020
comment
Да, вот и все ... Спасибо ... Я не знаю, почему строка кода не работает для одного конкретного пользовательского интерфейса, но другие отлично работают с кодом ... похоже, это единственная строка с раскадровкой хотя, и наличие кода не работает ... но когда мне это нравится из свойств раскадровки, это исправлено. спас день ... - person Rakshitha Muranga Rodrigo; 13.11.2020

Это сработало для меня

let vc = self.storyboard?.instantiateViewController(withIdentifier: "storyboardID_cameraview1") as! CameraViewController
  
vc.modalPresentationStyle = .fullScreen
    
self.present(vc, animated: true, completion: nil)`
person Guri S    schedule 01.11.2020

Вот простое решение без кодирования одной строки.

  • Выберите View Controller в раскадровке
  • Выберите инспектор атрибутов
  • Установите для презентации "Автоматически" значение "Полноэкранный", как показано на изображении ниже.

Это изменение делает поведение приложения iPad ожидаемым, в противном случае новый экран будет отображаться в центре экрана в виде всплывающего окна.

введите описание изображения здесь

person Mahesh Cheliya    schedule 19.10.2019
comment
Я думаю, что ключевым здесь является то, что вы сделали это в NavigationController, что и показано на рисунке, но в тексте это не сказано. - person Andy Weinstein; 17.02.2020
comment
также убедитесь, что последующие переходы отображаются, а не присутствуют в модальном режиме. - person Andy Weinstein; 18.02.2020
comment
Хорошо, поэтому мне кажется, что это работает, когда я использую контроллер панели вкладок для управления другими представлениями. Однако вам необходимо установить презентацию фактического «Контроллера панели вкладок» на полноэкранный режим, так как он управляет всеми другими представлениями. - person Charlie; 26.05.2020

Вот решение для Objective-C

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

vc.modalPresentationStyle = UIModalPresentationFullScreen;

[self presentViewController:vc animated:YES completion:nil];
person Prashanth Thota    schedule 13.11.2019

Если у вас есть UITabController с экранами со встроенными контроллерами навигации, вы должны установить UITabController Presentation на FullScreen, как показано на рисунке ниже.

введите описание изображения здесь

person Di Nerd    schedule 23.09.2019

Вот моя версия исправления в ObjectiveC с использованием категорий. При таком подходе у вас будет поведение UIModalPresentationStyleFullScreen по умолчанию, пока не будет явно установлено другое.

#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
person Alexander Kulabukhov    schedule 03.12.2019
comment
у вас есть файл .h? - person Pedro Góes; 28.01.2020
comment
@ PedroGóes да, но он состоит только из объявления категории: `` @interface UIViewController (Presentation) @end '' - person Alexander Kulabukhov; 28.01.2020

Все остальные ответы достаточны, но для такого большого проекта, как наш, где навигация осуществляется как в коде, так и в раскадровке, это довольно сложная задача.

введите описание изображения здесь

Для тех, кто активно использует Storyboard. Это мой совет: используйте Regex.

Следующий формат не подходит для полноэкранных страниц:

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

Для полноэкранных страниц подходит следующий формат:

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

Следующее регулярное выражение, совместимое с VS CODE, преобразует все страницы старого стиля в страницы нового стиля. Вам может потребоваться экранировать специальные символы, если вы используете другие движки регулярных выражений / текстовые редакторы.

Искать Regex

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

Заменить Regex

<segue destination="$1" kind="presentation" identifier="$2" modalPresentationStyle="fullScreen" id="$3"/>
person Bangonkali    schedule 25.10.2019

Первоначально значение по умолчанию для modalPresentationStyle - fullscreen, но в iOS 13 оно изменилось на UIModalPresentationStyle.automatic.

Если вы хотите сделать контроллер полноэкранного просмотра, вам нужно изменить modalPresentationStyle на fullScreen.

Дополнительные сведения см. В UIModalPresentationStyle документации Apple и рекомендации по человеческому интерфейсу Apple, где и какую модальность следует использовать.

person yo2bh    schedule 06.11.2019
comment
Это правильный ответ, начиная с iOS 13.3, Xcode 11.3, для ситуаций, когда вы хотите представить viewController ИЗ a navigationController. Также работает modalPresentationStyle из .overFullScreen. Однако, если вы представляете navigationController, вам необходимо установить 'modalPresentationStyle' в navigationController, а не в viewController. Ваше здоровье. - person Womble; 16.01.2020

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

// если вы хотите отключить смахивание, чтобы закрыть его, добавьте строку

Obj.isModalInPresentation = true

Дополнительные сведения см. В документе Apple.

person Mohit Tomar    schedule 25.09.2019

Вы можете легко это сделать. Откройте свою раскадровку как исходный код и найдите kind="presentation", во всех тегах seague с kind = presentation добавьте дополнительный атрибут modalPresentationStyle="fullScreen"

person amar    schedule 26.11.2019

Я добился этого с помощью метода swizzling (Swift 4.2):

Чтобы создать расширение UIViewController следующим образом

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

и в AppDelegate в application: didFinishLaunchingWithOptions: вызовите swizzling-код, вызвав:

UIViewController.setPresentationStyle_fullScreen()
person Sreeraj VR    schedule 24.05.2020
comment
Очень хакерское решение. Вы могли бы достичь того же результата с помощью обычного подкласса UIViewController и избежать свиззинга. Теперь, если я извлечу несколько экранов в фреймворк, у меня не будет там swizzled-методов. Излишне говорить, что это сложно найти, если вы унаследовали проект. Вам следует избегать употребления алкоголя, как чумы. Не даст -1, поскольку решает проблему, но ломает SOLID, поскольку теперь AppDelegate необходим для настройки контроллеров представления и может создать беспорядок в будущих версиях iOS. - person Martin Berger; 09.11.2020
comment
@MartinBerger, решение будет полезно, если вы попытаетесь перенести свой старый код на новый, и оно не рекомендуется для новых проектов. - person Sreeraj VR; 10.11.2020

Установка navigationController.modalPresentationStyle на .fullScreen здесь повторялась более тысячи раз, но позвольте мне представить вам еще один блокировщик, из-за которого UIViewController / UINavigationController не отображался в fullscreen, хотя все свойства были установлены правильно.

В моем случае виновник был скрыт в этой строке

navigationController?.presentationController?.delegate = self

Очевидно, установка UIAdaptivePresentationControllerDelegate меняет стиль на pageSheet.

person skornos    schedule 26.03.2021

Создайте категорию для UIViewController (скажем, UIViewController + PresentationStyle). Добавьте к нему следующий код.

 -(UIModalPresentationStyle)modalPresentationStyle{
     return UIModalPresentationStyleFullScreen;
}
person Govind    schedule 25.11.2019
comment
это сломает UISearchController + вызовет сложный для отладки сбой - person dklt; 13.01.2020
comment
@dklt Замечательное наблюдение. Таким образом, явная установка свойства решит проблему. Нет более простых решений, если используется UISearchController. - person Govind; 16.01.2020

альтернативный подход состоит в том, чтобы иметь собственный компонент базового контроллера представления в вашем приложении и просто реализовать назначенные и необходимые инициализаторы с базовой настройкой, примерно так:

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

Надеюсь, это поможет

person Luca Iaco    schedule 09.10.2019

Приведенные выше ответы и предложения верны, ниже - другая версия и эффективный способ программного использования.

# 1 Создал расширение UIView

# 2 Создан метод ()

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

ИЛИ

let vc = MyViewController()
sourceView.presentLocal(vc, animated: true, completion: nil)
person Master_Tushar    schedule 05.10.2019

class MyViewController: UIViewController {

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

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

Вместо того, чтобы вызывать self.modalPresentationStyle = .fullScreen для каждого контроллера представления, вы можете создать подкласс UIViewController и просто использовать MyViewController везде.

person Peter Tao    schedule 18.10.2019