[ios] iOS 13 전체 화면에서 모달 표시

iOS 13에는 모달 뷰 컨트롤러가 표시 될 때 새로운 동작이 있습니다.

이제 기본적으로 전체 화면이 아니며 아래로 슬라이드하려고하면 앱이 View Controller를 자동으로 닫습니다.

이 동작을 방지하고 이전 전체 화면 모달 vc로 돌아가려면 어떻게해야합니까?

모달 행동

감사



답변

WWDC 2019 에서 Platforms of the Union에 언급 된대로 iOS 13을 사용하여 Apple은 새로운 기본 카드 프리젠 테이션을 도입했습니다. 전체 화면을 강제 실행하려면 다음과 같이 명시 적으로 지정해야합니다.

let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen //or .overFullScreen for transparency
self.present(vc, animated: true, completion: nil)


답변

누군가에게 유용한 정보를 추가합니다. 스토리 보드 segue가있는 경우 이전 스타일로 돌아가려면 kind 속성을 Present Modally 로 설정 하고 Presentation 속성을 Full Screen 으로 설정해야합니다 .

여기에 이미지 설명을 입력하십시오


답변

시작 화면 직후의 초기보기 에서이 문제가 발생했습니다. 정의 또는 논리가 정의되지 않았기 때문에 해결 방법은 다음과 같이 프레젠테이션을 자동에서 전체 화면으로 전환하는 것이 었습니다.

fix_storyboard_presentation_default_behavior


답변

여러 가지 방법이 있으며 각 프로젝트는 하나의 프로젝트에는 적합하지만 다른 프로젝트에는 적합하지 않다고 생각하므로 다른 사람이 다른 사건을 겪을 수도 있습니다.

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- 스토리 보드에서

segue를 선택하고 프레젠테이션을로 설정하십시오 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/


답변

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
}


답변

Objective-C 사용자의 경우

이 코드를 사용하십시오

 [vc setModalPresentationStyle: UIModalPresentationFullScreen];

또는 iOS 13.0에서 특정 항목을 추가하려면

 if (@available(iOS 13.0, *)) {
     [vc setModalPresentationStyle: UIModalPresentationFullScreen];
 } else {
     // Fallback on earlier versions
 }


답변


짧막 한 농담:

modalPresentationStyle표시되는 navigationController에서 설정해야합니다 .


아이폰 OS (13)와 아이폰 OS 버전의 전체 화면 아래 overCurrentContext
navigationController

테스트 된 코드

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

modalPresentationStylenavigationController 에서 설정해야합니다 .