제시된보기 컨트롤러 닫기


116

이론적 인 질문이 있습니다. 이제 Apple의 ViewController 가이드를 읽고 있습니다.

그들은 작성했다:

제시된 뷰 컨트롤러를 해제 할 때 선호되는 접근 방식은 제시 뷰 컨트롤러가 해제하도록하는 것입니다. 즉, 가능할 때마다 뷰 컨트롤러를 표시 한 동일한 뷰 컨트롤러가이를 해제 할 책임이 있습니다. 프리젠 테이션 뷰 컨트롤러에게 제시된 뷰 컨트롤러를 해제해야 함을 알리는 몇 가지 기술이 있지만, 선호하는 기법은 위임입니다.

하지만 제시된 VC에서 프로토콜을 생성하고 델리게이트 변수를 추가해야하는 이유를 설명 할 수 없습니다. 제시된 뷰 컨트롤러 메서드 에서 간단한 호출 대신 제시된 VC를 해제하기 위해 VC를 제시 할 때 델리게이트 메서드를 생성해야합니다.

[self dismissViewControllerAnimated:NO completion:nil]?

첫 번째 선택이 더 나은 이유는 무엇입니까? Apple이 권장하는 이유는 무엇입니까?

답변:


122

나는 애플이 잠재적으로 복잡한 API 조각을 위해 약간의 등을 덮고 있다고 생각합니다.

  [self dismissViewControllerAnimated:NO completion:nil]

실제로 약간의 바이올린입니다. 제시된 뷰 컨트롤러에서 합법적으로 이것을 호출 할 수 있지만, 그것이하는 일은 메시지를 제시하는 뷰 컨트롤러로 전달하는 것뿐입니다. VC를 무시하는 것 이상으로 무언가를하고 싶다면 이것을 알아야하고, 델리게이트 메서드와 거의 같은 방식으로 처리해야합니다. 위임 방법.

아마도 그들은 이것이 어떻게 결합되는지 실제로 이해하지 못하는 사람들에 의해 많은 나쁜 코드를 발견했을 것입니다.

하지만 물론, 당신이해야 할 일이 그 일을 무시하는 것이라면 계속 진행하십시오.

내 접근 방식은 타협입니다. 적어도 무슨 일이 일어나고 있는지 상기시켜줍니다.

  [[self presentingViewController] dismissViewControllerAnimated:NO completion:nil]

[빠른]

  self.presentingViewController?.dismiss(animated: false, completion:nil)

26
사용 presentingViewController하는 것은 UINavigationControllerif self가 하나에 포함되어 있음 을 나타내므로 거의 쓸모가 없습니다 . 어떤 경우에는 전혀 얻을 수 없습니다 presentingViewController. 그러나이 경우 [self dismissViewControllerAnimated:completion]에도 여전히 작동합니다. 내 제안은 Apple이 고칠 때까지 계속 사용하는 것입니다.
memmons

4
이 답변이 3 년 후에도 여전히 완전히 관련이 있다는 점을 좋아합니다.
user1021430

1
고려해야 할 다른 점은 뷰 컨트롤러가 그것이 어떻게 표시되었는지 모른다는 것입니다. 그것은 제시되고, 네비게이션 컨트롤러, 탭바 컨트롤러의 일부 등에 푸시되었을 수 있습니다. 델리게이트를 사용하면 "프레젠테이션"뷰 컨트롤러가 그것을 제시하는 데 사용 된 방법의 역을 사용하여 뷰 컨트롤러를 "해제"할 수 있습니다.
David Smith

51

Swift 3 업데이트

나는 현재 (제공된) View Controller를 무시하고 싶었습니다. 나는 같은 목적으로 여기에 오는 모든 사람들을 위해이 대답을 만들고 있습니다.

네비게이션 컨트롤러

내비게이션 컨트롤러를 사용하는 경우 매우 쉽습니다.

이전 뷰 컨트롤러로 돌아갑니다.

// Swift
self.navigationController?.popViewController(animated: true)

// Objective-C
[self.navigationController popViewControllerAnimated:YES];

루트 뷰 컨트롤러로 돌아갑니다.

// Swift
self.navigationController?.popToRootViewController(animated: true)

// Objective-C
[self.navigationController popToRootViewControllerAnimated:YES];

( 이 답변 덕분에 Objective-C에 대한 에 .)

모달 뷰 컨트롤러

뷰 컨트롤러가 모달로 표시되면 다음을 호출하여 두 번째 뷰 컨트롤러에서 해제 할 수 있습니다.

// Swift
self.dismiss(animated: true, completion: nil)

// Objective-C
[self dismissViewControllerAnimated:YES completion:nil];

설명서를 말한다

프레젠테이션 뷰 컨트롤러는 자신이 제시 한 뷰 컨트롤러를 해제 할 책임이 있습니다. 제시된 뷰 컨트롤러 자체에서이 메서드를 호출하면 UIKit은 제시 뷰 컨트롤러에게 해제를 처리하도록 요청합니다.

따라서 제시된 뷰 컨트롤러가 자체적으로 호출하도록 작동합니다. 다음 은 전체 예입니다.

대표자

OP의 질문은 델리게이트를 사용하여 뷰를 무시하는 복잡성에 관한 것이 었습니다.

지금까지는 일반적으로 내비게이션 컨트롤러 나 모달 뷰 컨트롤러가 있으므로 델리게이트 를 사용할 필요가 없었지만 나중에 델리게이트 패턴 을 사용해야 하는 경우 업데이트를 추가하겠습니다.


50

이는 뷰 컨트롤러 재사용을위한 것입니다.

뷰 컨트롤러는 그것이 모달로 표시되는지, 탐색 컨트롤러에 푸시되는지 또는 무엇이든 상관하지 않아야합니다. 뷰 컨트롤러가 자동으로 해제되면 모달로 표시되는 것으로 간주됩니다. 해당 뷰 컨트롤러를 탐색 컨트롤러에 푸시 할 수 없습니다.

프로토콜을 구현하면 부모 뷰 컨트롤러가 표시 / 푸시 및 해제 / 팝 방식을 결정할 수 있습니다.



6

내 경험상 어느에서나 해산해야 할 때 유용 합니다. 당신이 원하는의 ViewController와 일축를하는 각의 ViewController에 대해 서로 다른 작업을 수행합니다. 프로토콜을 채택하는 모든 viewController는 자체 방식으로 뷰를 닫을 수 있습니다. (ipad 대 iphone 또는 다른보기에서 닫을 때 다른 데이터 전달, 닫을 때 다른 메소드 호출 등)

편집하다:

따라서 명확히하기 위해보기를 닫고 싶은 경우 위임 프로토콜을 설정할 필요가 없습니다. 다른 프리젠 테이션 뷰 컨트롤러에서 해제 한 후 다른 작업을 수행해야하는 경우 대리자를 사용하는 가장 좋은 방법입니다.


하지만 "다른 뷰에서 닫을 때 다른 데이터 전달, 닫을 때 다른 메서드 호출 등"이 필요하지 않은 경우 제시된 뷰 컨트롤러 메서드에서 한 번만 호출 할 수 있습니까? [self dismissViewControllerAnimated : NO 완료 : nil]?
nikitahils 2013 년

발표자가 제시된 뷰를 닫게하면 발표자가 실제로 준비가되어 있고 포 그라운드로 돌아가는 작업을 처리하고 있음을 분명히 알 수 있습니다. 실행 순서를 따르기 쉽고 모든 UI 업데이트의 책임이 암시 적으로 명확 해집니다.
Johan

2

View Controller 프로그래밍 가이드 , "View Controller가 다른 View Controller를 나타내는 방법" 에서 인용 .

제시된 뷰 컨트롤러 체인의 각 뷰 컨트롤러에는 체인에서 주변의 다른 객체에 대한 포인터가 있습니다. 즉, 다른 뷰 컨트롤러를 제공하는 제시된 뷰 컨트롤러는 presentingViewController 및 presentationViewController 속성 모두에 유효한 개체를 가지고 있습니다. 이러한 관계를 사용하여 필요에 따라 뷰 컨트롤러 체인을 추적 할 수 있습니다. 예를 들어 사용자가 현재 작업을 취소하는 경우 첫 번째로 제시된 뷰 컨트롤러를 해제하여 체인의 모든 개체를 제거 할 수 있습니다. 뷰 컨트롤러를 해제하면 해당 뷰 컨트롤러뿐만 아니라 표시 한 뷰 컨트롤러도 모두 해제됩니다.

그래서 한편으로는 균형 잡힌 디자인, 좋은 디커플링 등을 만듭니다. 그러나 다른 한편으로는 탐색의 특정 지점으로 빠르게 돌아갈 수 있기 때문에 매우 실용적입니다.

비록 나는 개인적으로 제시하는 뷰 컨트롤러 트리를 뒤로 넘기 려고하기 보다는 풀기 세그를 사용하는 편이 더 낫다. 애플이이 챕터에서 인용 한 내용이다.


2

한 가지 요점은 이것이 좋은 코딩 접근 방식이라는 것입니다. OOPSRP, 관심사 분리 등 많은 원칙을 충족합니다 .

따라서 뷰를 제공하는 뷰 컨트롤러는 뷰를 해제하는 컨트롤러 여야합니다.

마찬가지로 집을 빌려주는 부동산 회사가 집을 되 찾을 권한이 있어야합니다.


2

Swift 3.0 // 빠른보기 컨트롤러 닫기

self.navigationController?.popViewController(animated: true)
dismiss(animated: true, completion: nil)

1

Michael Enriquez의 답변 외에도 이것이 결정되지 않은 상태로부터 자신을 보호하는 좋은 방법이 될 수있는 또 다른 이유를 생각할 수 있습니다.

ViewControllerA가 ViewControllerB를 모달로 제공한다고 가정합니다. 그러나 ViewControllerA에 대한 코드를 작성하지 않았을 수 있으므로 ViewControllerA의 수명주기를 알지 못합니다. 뷰 컨트롤러 인 ViewControllerB를 표시 한 후 5 초 (예 :)를 닫을 수 있습니다.

이 경우 단순히 사용하는 경우 dismissViewController ViewControllerB에서 자신을 해제하기 위해 하는 경우 정의되지 않은 상태가됩니다. 아마도 충돌이나 검은 화면이 아니라 관점에서 정의되지 않은 상태가 될 것입니다.

대신 대리자 패턴을 사용하는 경우 ViewControllerB의 상태를 알고 내가 설명한 것과 같은 경우에 대해 프로그래밍 할 수 있습니다.


1

빠른

let rootViewController:UIViewController = (UIApplication.shared.keyWindow?.rootViewController)!

        if (rootViewController.presentedViewController != nil) {
            rootViewController.dismiss(animated: true, completion: {
                //completion block.
            })
        }

0

모달을 사용하는 경우 view dismiss를 사용하십시오.

[self dismissViewControllerAnimated:NO completion:nil];

이것은 "왜 첫 번째 선택이 더 나은가? Apple이 권장하는 이유는 무엇입니까?"
jww

0

이것은 많은 말썽 꾸러기입니다. 위임은 필요할 때는 괜찮지 만 코드를 더 복잡하게 만들고 그렇게하는 경우에는 그 이유가 있어야합니다.

나는 애플이 그 이유를 가지고 있다고 확신한다. 그러나 다른 일을 할 진정한 이유가없고 오늘까지 내가 볼 수있는 것을 제시 한 사람이없는 한, 제시된 VC가 해고를하도록하는 것이 더 명확하고 간결합니다.

프로토콜은 필요할 때 탁월하지만 객체 지향 설계는 모듈이 서로 불필요하게 통신하는 것이 아닙니다.

Tom Love (Objective C의 공동 개발자)는 Objective C가 "우아함", "작음", "선명함"및 "잘 정의 됨"(C ++과 비교할 때)이라고 언급 한 적이 있습니다. 쉽게 말할 수 있습니다. 위임은 "그냥"과도하게 사용 된 것처럼 보이는 유용한 기능입니다. 저는 언어 작업을 좋아하지만 불필요한 구문을 사용하여 필요한 것보다 더 복잡하게 만들어야한다는 생각이 두렵습니다.


처음에는 약간의 코드를 절약 할 수 있지만, 코드 기반이 커짐에 따라 접근 방식은 많은 고통을 유발합니다. 관심사 분리와 같은 객체 지향 원칙을 이해해야합니다. 그렇지 않으면 전체 애플리케이션을 하나의 큰 파일로 코딩하는 것이 좋습니다.
Werner Altewischer

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.