[ios] iOS 13에서 시트 감지가 닫혔습니다.

iOS 13 이전에는 전체 화면을 덮는 데 사용되는 뷰 컨트롤러가 제시되었습니다. 그리고 해제되면 상위 뷰 컨트롤러 viewDidAppear기능이 실행되었습니다.

이제 iOS 13은 뷰 컨트롤러를 기본으로 시트로 표시합니다. 즉, 카드가 기본 뷰 컨트롤러를 부분적으로 덮을 것입니다. 즉 viewDidAppear, 부모 뷰 컨트롤러가 실제로 사라지지 않았기 때문에 호출되지 않습니다.

제시된 뷰 컨트롤러 시트가 닫 혔음감지 하는 방법이 있습니까? 어떤 종류의 델리게이트를 사용 하는 대신 부모 뷰 컨트롤러에서 재정의 할 수있는 다른 기능이 있습니까?



답변

제시된 뷰 컨트롤러 시트가 닫 혔음을 감지하는 방법이 있습니까?

예.

어떤 종류의 델리게이트를 사용하는 대신 부모 뷰 컨트롤러에서 재정의 할 수있는 다른 기능이 있습니까?

아니요. “어떤 종류의 대리인”이 당신이하는 방식입니다. 자신을 프레젠테이션 컨트롤러의 델리게이트로 만들고 presentationControllerDidDismiss(_:).

https://developer.apple.com/documentation/uikit/uiadaptivepresentationcontrollerdelegate/3229889-presentationcontrollerdiddismiss


전체 화면이든 아니든, 제시된 뷰 컨트롤러가 닫 혔음을 알리는 일반적인 런타임 생성 이벤트의 부족은 실제로 문제가됩니다. 그러나 항상 전체 화면이 아닌 뷰 컨트롤러가 있기 때문에 새로운 문제는 아닙니다. 이제 (iOS 13에서) 더 많은 것들이 있습니다! 다른 곳에서이 주제에 대해 별도의 질문과 대답을 할애합니다. Unified UIViewController가 “최전방이 된”탐지입니까? .


답변

다음 은 시트로 표시되는 자식 뷰 컨트롤러 (즉, 기본 iOS 13 방식)가 닫힐 때 알림을받는 부모 뷰 컨트롤러의 코드 예제입니다 .

public final class Parent: UIViewController, UIAdaptivePresentationControllerDelegate
{
  // This is assuming that the segue is a storyboard segue; 
  // if you're manually presenting, just see the delegate there.
  public override func prepare(for segue: UIStoryboardSegue, sender: Any?)
  {
    if segue.identifier == "mySegue" {
      segue.destination.presentationController?.delegate = self;
    }
  }

  public func presentationControllerDidDismiss(
    _ presentationController: UIPresentationController)
  {
    // Only called when the sheet is dismissed by DRAGGING.
    // You'll need something extra if you call .dismiss() on the child.
    // (I found that overriding dismiss in the child and calling
    // presentationController.delegate?.presentationControllerDidDismiss
    // works well).
  }
}

Jerland2의 대답은 시트가 될 때 (A) 원래 질문자가 함수 호출을받을 싶어하기 때문에, 혼란 기각 (그가 전화했을 때 사용자가 시도되고 presentationControllerDidAttemptToDismiss 구현 반면 과 실패 , 그리고 (b) 설정 isModalInPresentation 시트를 닫를) 완전히 직교하며 실제로 제시된 시트를 닫을 수 없게 만듭니다 (OP가 원하는 것과 반대 임).


답변

또 다른 옵션은 다시 얻을 수 viewWillAppearviewDidAppear세트입니다

let vc = UIViewController()
vc.modalPresentationStyle = .fullScreen

이 옵션은 전체 화면을 덮고 닫은 후 위의 메서드를 호출합니다.


답변

미래의 독자를 위해 여기에 구현에 대한 더 완전한 답변이 있습니다.

  1. 루트 뷰 컨트롤러에서 segue를 준비하려면 다음을 추가하십시오 (모달에 nav 컨트롤러가 있다고 가정)
    // Modal Dismiss iOS 13
    modalNavController.presentationController?.delegate = modalVc
  1. 모달 뷰 컨트롤러에서 다음 대리자 + 메서드를 추가합니다.
// MARK: - iOS 13 Modal (Swipe to Dismiss)

extension ModalViewController: UIAdaptivePresentationControllerDelegate {
    func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) {


        print("slide to dismiss stopped")
        self.dismiss(animated: true, completion: nil)
    }
}
  1. 모달 뷰 컨트롤러에서 대리자 메서드를 호출하려면 다음 속성이 참인지 확인하십시오.
    self.isModalInPresentation = true
  1. 이익


답변

빠른

호출에 일반 솔루션 viewWillAppeariOS13

class ViewController: UIViewController {

        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            print("viewWillAppear")
        }

        //Show new viewController
        @IBAction func show(_ sender: Any) {
            let newViewController = NewViewController()
            //set delegate of UIAdaptivePresentationControllerDelegate to self
            newViewController.presentationController?.delegate = self
            present(newViewController, animated: true, completion: nil)
        }
    }

    extension UIViewController: UIAdaptivePresentationControllerDelegate {
        public func presentationControllerDidDismiss( _ presentationController: UIPresentationController) {
            if #available(iOS 13, *) {
                //Call viewWillAppear only in iOS 13
                viewWillAppear(true)
            }
        }
    }


답변

DRAG OR CALL DISMISS FUNC는 아래 코드에서 작동합니다.

1) 루트 뷰 컨트롤러에서 아래 코드와 같이 프레젠테이션 뷰 컨트롤러가 무엇인지 알려줍니다.

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "presenterID" {
        let navigationController = segue.destination as! UINavigationController
        if #available(iOS 13.0, *) {
            let controller = navigationController.topViewController as! presentationviewcontroller
            // Modal Dismiss iOS 13
            controller.presentationController?.delegate = self
        } else {
            // Fallback on earlier versions
        }
        navigationController.presentationController?.delegate = self

    }
}

2) 다시 루트 뷰 컨트롤러에서 프레젠테이션 뷰 컨트롤러가 해산 될 때 수행 할 작업을 알려줍니다.

public func presentationControllerDidDismiss(
  _ presentationController: UIPresentationController)
{
    print("presentationControllerDidDismiss")
}

1) 프레젠테이션 뷰 컨트롤러에서이 그림에서 취소 또는 저장 버튼을 누르면. 아래 코드가 호출됩니다.

self.dismiss(animated: true) {
        self.presentationController?.delegate?.presentationControllerDidDismiss?(self.presentationController!)
    }

여기에 이미지 설명 입력


답변

해제되는 UIViewController에서 viewWillDisappear를 재정의합니다. isBeingDismissed부울 플래그 를 통해 해고를 알립니다 .

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if isBeingDismissed {
        print("user is dismissing the vc")
    }
}

** 사용자가 아래로 스 와이프하고 카드를 다시 위로 스 와이프하면 카드가 해제되지 않은 경우에도 해제 된 것으로 등록됩니다. 그러나 그것은 당신이 신경 쓰지 않을 수있는 가장 중요한 경우입니다.