提示されたView Controllerを閉じる


116

理論的な質問があります。さて、AppleのViewControllerガイドを読んでいます。

彼らが書きました:

提示されたビューコントローラーを却下するときがきたとき、推奨されるアプローチは、提示されたビューコントローラーに却下することです。言い換えると、可能な場合は常に、View Controllerを提示した同じView Controllerがそれを閉じる責任も負う必要があります。提示されたビューコントローラを閉じる必要があることを提示するビューコントローラに通知するためのいくつかの手法がありますが、好ましい手法は委譲です。

私が提示VCでのプロトコルを作成し、デリゲートvaribleを追加し、提示VCを退けるためにVCを提示してデリゲートメソッドを作成する必要がありますしかし、なぜ私の代わりに、単純なコールを、説明することはできません提示ビューコントローラメソッド

[self dismissViewControllerAnimated:NO completion:nil]

なぜ最初の選択肢が優れているのですか?Appleが推奨する理由

回答:


122

Appleは、潜在的に不器用なAPIのために、ここで少し背を向けていると思います。

  [self dismissViewControllerAnimated:NO completion:nil]

実際にはちょっとしたフィドルです。あなたは-正当に-提示されたビューコントローラでこれを呼び出すことができますが、それはすべて提示するビューコントローラにメッセージを転送することです。VCを閉じるだけでなく、何でもやりたい場合は、これを知っておく必要があります。デリゲートメソッドとほとんど同じ方法で扱う必要があります。デリゲートメソッド。

おそらく、これがどのように組み合わされているかを実際に理解していない人々によって大量の不良コードに遭遇したので、彼らは注意を払っています。

しかし、もちろん、あなたがする必要があるすべてが事を却下することであるなら、先に進んでください。

私自身のアプローチは妥協です、少なくともそれは私に何が起こっているのかを思い出させます:

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

[迅速]

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

26
if が1に埋め込まれpresentingViewControllerていることを指すので、使用してもほとんど役に立たないことに注意してください。その場合、あなたはまったく手に入れることができなくなります。しかし、その場合でも機能します。私の提案は、Appleが修正するまでそれを使い続けることです。UINavigationControllerselfpresentingViewController[self dismissViewControllerAnimated:completion]
memmons 2014年

4
この回答が3年後も完全に関連していることを嬉しく思います。
user1021430 2017

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 に対するこの回答に感謝します。)

モーダルビューコントローラー

ビューコントローラーがモーダルで表示されている場合、次の呼び出しによって(2番目のビューコントローラーから)ビューコントローラーを終了できます

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

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

ドキュメントは言います、

提示するビューコントローラは、提示したビューコントローラを閉じる責任があります。提示されたビューコントローラー自体でこのメソッドを呼び出すと、UIKitは提示されたビューコントローラーに破棄の処理を要求します。

したがって、提示されたビューコントローラーがそれ自体を呼び出すように機能します。ここに完全な例があります。

代議員

OPの質問は、デリゲートを使用してビューを却下することの複雑さについてでした。

この時点では、通常はナビゲーションコントローラーまたはモーダルビューコントローラーがあるため、デリゲートを使用する必要はありませんが、将来デリゲートパターンを使用する必要がある場合は、更新を追加します。


50

これはView Controllerの再利用性のためです。

ビューコントローラーは、それがモーダルとして表示されているか、ナビゲーションコントローラーにプッシュされているか、その他何でもかまいません。ビューコントローラーがそれ自体を閉じる場合は、モーダルで表示されていると想定しています。そのビューコントローラーをナビゲーションコントローラーにプッシュすることはできません。

プロトコルを実装することにより、親のビューコントローラーに、それをどのように表示/プッシュおよび却下/ポップするかを決定させます。



6

私の経験では、必要 ViewController からそれを閉じる必要があり、それを閉じるビューコントローラごとに異なるタスクを実行する必要がある場合に便利です。プロトコルを採用する任意のviewControllerは、独自の方法でビューを閉じることができます。(ipadとiphone、または異なるビューから閉じるときに異なるデータを渡す、閉じるときに異なるメソッドを呼び出すなど)

編集:

したがって、明確にするために、ビューを閉じることが目的の場合は、デリゲートプロトコルを設定する必要はありません。表示している別のView Controllerから閉じた後で別のことを行う必要がある場合は、デリゲートを使用するのに最適な方法です。


しかし、「別のビューから閉じるときに別のデータを渡す、閉じるときに別のメソッドを呼び出すなど」必要がない場合は、表示されたビューコントローラーメソッドで1つの小さな呼び出しを実行できます-[self dismissViewControllerAnimated:NO completion:nil]?
nikitahils 2013年

プレゼンターに提示されたビューを却下させると、プレゼンターが実際に準備ができており、フォアグラウンドへの戻りを処理していることが明らかになります。実行シーケンスは簡単に追跡でき、UI更新の責任は暗黙的に明確になります。
ヨハン

2

View Controllerプログラミングガイドの「View Controllersが他のView Controllerを提示する方法からの引用。

提示されたビューコントローラーのチェーン内の各ビューコントローラーには、チェーン内でそれを囲む他のオブジェクトへのポインターがあります。言い換えると、別のビューコントローラを提示する提示されたビューコントローラは、presentingViewControllerプロパティとpresentedViewControllerプロパティの両方に有効なオブジェクトを持っています。これらの関係を使用して、必要に応じてView Controllerのチェーンをたどることができます。たとえば、ユーザーが現在の操作をキャンセルした場合、最初に表示されたビューコントローラーを閉じることにより、チェーン内のすべてのオブジェクトを削除できます。ビューコントローラーを閉じると、そのビューコントローラーだけでなく、表示されたビューコントローラーもすべて閉じます。

したがって、一方ではバランスの取れたデザイン、優れたデカップリングなどを実現します。しかし、他方では、ナビゲーションの特定のポイントにすばやく戻ることができるため、非常に実用的です。

でも個人的には ビューコントローラツリーを逆方向にたどるので巻き戻しセグエを勧めします


2

1つは、これが優れたコーディング方法であることです。それは多くを満たしますOOPSRP、懸念の分離など、原則をます。

したがって、ビューを提示するビューコントローラは、それを非表示にするビューコントローラである必要があります。

同様に、家を賃貸で提供する不動産会社は、それを取り戻す権限を持つべきです。


2

Swift 3.0 // Swiftで View Controllerを閉じる

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

1

マイケルエンリケスの答えに加えて、これが未確定の状態から身を守るための良い方法である理由がもう1つ考えられます。

たとえば、ViewControllerAがViewControllerBをモーダルで提示するとします。ただし、ViewControllerAのコードを記述していない可能性があるため、ViewControllerAのライフサイクルを認識していません。View ControllerBを提示してから5秒(たとえば)終了する場合があります。

この場合、単に使用していた場合 dismissViewController ViewControllerBをして自分自身を閉じると、最終的には未定義の状態になります。おそらく、クラッシュや黒い画面ではなく、ユーザーの観点からは未定義の状態です。

代わりに、デリゲートパターンを使用している場合は、ViewControllerBの状態を認識しており、前述のケースのようにプログラムできます。


1

迅速

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

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

0

モーダルを使用している場合は、ビューを閉じます。

[self dismissViewControllerAnimated:NO completion:nil];

これはどのようにして質問に答えますか:「なぜ最初の選択肢が優れているのですか?なぜAppleはそれを推奨しているのですか?」
JWW

0

これはたくさんのバニーです。委任は必要な場合は問題ありませんが、コードがより複雑になると(実際にはそうなります)、理由が必要になります。

Appleにはその理由があるに違いない。しかし、特に理由がない限り、提示されたVCが単に却下を行うほうがより明確で簡潔です。今日のように、ここで誰も私が見ることができるものを提示していません。

プロトコルは必要なときに優れていますが、オブジェクト指向の設計では、モジュールが互いに不必要に通信することは決してありませんでした。

Tom Love(Objective Cの共同開発者)は、Objective Cは「エレガント」、「小さく」、「くっきり」、そして「明確」(C ++と比較した場合)であるとコメントしていました。彼が言うのは簡単です。委任は、「単に」という理由で過度に使用されているように見える便利な機能であり、私はその言語での作業が好きなのですが、不必要な構文を使用して、必要以上に複雑にするために強制されてしまうのではないかと思います。


最初はいくつかのコードを節約できますが、このアプローチでは、コードベースが大きくなるにつれて多くの頭痛が発生します。関心事の分離などのオブジェクト指向の原則を理解する必要があります。そうでなければ、アプリケーション全体を1つの大きなファイルにコーディングすることもできます。
Werner Altewischer 2017年

-2

スーパービューウィンドウを閉じることができます

self.view.superview?.window?.close()

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.