2013-01-31 40 views
79

我有一個理論問題。現在,我們正在閱讀Apple的ViewController指南。解散呈現的視圖控制器

他們寫道:

當談到時間駁回呈現視圖控制器,該 首選的方法是讓呈現視圖控制器駁回 它。換句話說,只要有可能, 呈現給視圖控制器的相同視圖控制器也應該對 負責解除視圖控制器。雖然有幾種技術用於通知 呈現視圖控制器,其所呈現的視圖控制器應當解除 ,但首選技術是委派。

但我無法解釋,爲什麼我必須按照所呈現VC創建一個協議,並添加代表varible,在介紹VC解僱呈現VC創建委託方法,而不是在一個簡單的通話提出視圖控制器方法

[self dismissViewControllerAnimated:NO completion:nil]

爲什麼第一個選擇更好?蘋果爲什麼推薦它?

回答

6

以我的經驗,它派上用場的時候,你需要從駁回任何你想要的的ViewController併爲駁斥其每個視圖 - 控制執行不同的任務。任何採用該協議的viewController都可以以自己的方式解除視圖。 (新iPad VS iphone,或從不同的角度解僱時,駁回時調用不同的方法傳遞不同的數據,等等。)

編輯:

因此,要確認一下,如果所有你想做的事就是解僱查看,我看到沒有必要設置委託協議。如果你需要做不同的事情你從不同的呈現視圖控制器中解僱它,這將是你最好的方式去使用委託。

+0

但如果我不需要「從不同的看法解僱時,駁回時調用不同的方法等傳遞不同的數據。」我可以做呈現視圖控制器方法一個小電話 - - [self dismissViewControllerAnimated:NO完成:無]? – nikitahils

+0

是的,這就是我會做的。 – jhilgert00

+0

讓演示者忽略呈現的視圖,很明顯演示者實際上已經準備好並處理返回前景:執行順序很容易遵循,並且任何UI更新的責任都隱含地清晰。 – Johan

87

我認爲蘋果公司在這裏稍微掩蓋了他們的背影,可能會有一些API。

[self dismissViewControllerAnimated:NO completion:nil] 

實際上是一個小提琴。儘管您可以 - 合法地 - 在所呈現的視圖控制器上調用此函數,但它所做的只是將消息轉發給呈現視圖控制器。如果你想做任何事情,只要解僱VC,你就需要知道這一點,你需要像委託方法一樣對待它 - 因爲這幾乎就是它的原因,一個有點不靈活的委託方法。

也許他們遇到了許多不好的代碼,人們並沒有真正理解這是如何放在一起的,因此他們謹慎對待。

但是,當然,如果您只需要解僱這件事,那就繼續吧。

我自己的做法是一種妥協,至少它讓我想起了是怎麼回事:

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

[斯威夫特]

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

應該注意的是,使用'presentationViewController'基本上是無用的,因爲如果'self'被嵌入到'UINavigationController'中,它將會被引用。在這種情況下,你根本無法獲得'presentationViewController'。然而,'[self dismissViewControllerAnimated:completion]'仍然適用於這種情況。我的建議是繼續使用,直到Apple修復它。 – memmons

+1

我喜歡這個答案在3年後仍然完全相關。 – user1021430

42

這是視圖控制器可重用性。

你的視圖控制器不應該關心它是作爲模式呈現,推在導航控制器上,還是其他任何東西。如果您的視圖控制器自行解散,那麼您認爲它是以模態方式呈現的。您將無法將該視圖控制器推到導航控制器上。

通過實現一個協議,你讓父視圖控制器決定應該如何顯示/推送和取消/彈出。

0

如果您使用的是模態使用視圖關閉。

[self dismissViewControllerAnimated:NO completion:nil]; 
+0

這是如何回答這個問題的:*「爲什麼第一選擇更好?爲什麼蘋果會推薦它?」* – jww

2

引自查看Controller Programming Guide「視圖控制器如何呈現其他視圖控制器」。

呈現的視圖控制器鏈中的每個視圖控制器都有指向鏈中其他周圍對象的指針 。在其他 單詞中,呈現的視圖控制器呈現另一視圖控制器在它的呈現控制器和呈現視圖控制器屬性中均具有有效對象。根據需要,您可以使用這些關係通過視圖控制器鏈來跟蹤 。 例如,如果 用戶取消當前操作,則可以通過關閉第一個顯示的視圖控制器來刪除鏈中的所有對象( )。 關閉視圖控制器不僅會取消該視圖控制器 ,還會取消它提供的任何視圖控制器。

因此,一方面它使一個很好的平衡設計,良好的去耦,等...但在另一方面,這是非常實用的,因爲你可以迅速得到回導航某一點。

雖然,我個人寧可使用平倉塞格斯不是試圖向後遍歷呈現視圖控制器樹,這是蘋果公司關於本章當報價從會談。

2

有一點是,這是一種很好的編碼方法。它滿足了許多OOP原則,例如,SRP,顧慮分離等。

因此,呈現視圖的視圖控制器應該是解散它的視圖控制器。

像,一個房租公司誰應該有權收回租金。

0

這是很多的胡扯。授權在需要時很好,但如果它使代碼更加複雜 - 而且確實如此 - 則需要有一個原因。

我相信蘋果有它的理由。但是,如果沒有真正的理由去做這件事,那麼簡單地讓提出的風險投資者去解決這個問題就會更清楚,更簡潔,今天這裏沒有人提出我能看到的。

協議在需要時非常出色,但面向對象的設計永遠不會讓模塊彼此進行不必要的通信。目標C的共同開發者Tom Love曾經評論過Objective C是「優雅」,「小」,「清晰」和「明確定義」(與C++相比)。容易他說。授權是一個有用的功能,似乎已被「過度使用」,雖然我喜歡使用該語言,但我害怕使用不必要的語法來使事情變得比事實複雜得多的想法。

+0

它可能會最初爲您節省一些代碼,但隨着代碼庫的增長,您的方法會導致許多頭痛。你應該理解面向對象的原則,比如分離關注點,否則你不妨將整個應用程序編碼成一個大文件。 –

33

更新了斯威夫特3

我來這裏只是想關閉當前(呈現)視圖控制器。對於任何來到這裏的人都有同樣的目的,我正在給出這個答案。

導航控制器

如果您使用的是導航控制器,那麼它是很容易的。

返回到先前的視圖控制器:

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

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

返回到根視圖控制器:(。感謝this answer爲目的-C)

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

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

模態視圖控制器

當一個視圖控制器有模式呈現,你可以通過調用

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

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

documentation說,關閉它(從第二個視圖控制器),

的呈現視圖控制器負責駁回查看 它呈現的控制器。如果您在所呈現的視圖 控制器本身上調用此方法,UIKit會要求呈現視圖控制器處理 解僱。

所以它適用於所呈現的視圖控制器調用它本身。 Here就是一個完整的例子。

代表

的OP的問題是關於使用委託駁回視圖的複雜性。

對於這一點我沒有必要使用委託,因爲我通常有一個導航控制器或模式視圖控制器,但是如果我需要在未來使用the delegate pattern,我會添加更新。

5

試試這個:

[self dismissViewControllerAnimated:true completion:nil]; 
2

雨燕3.0 //辭退查看控制器在迅速

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

除了邁克爾·恩裏克斯的回答,我能想到的另外一個原因,這可能是保護自己免於未確定狀態的好方法:

說說ViewControllerA呈現ViewController B模態。但是,由於您可能沒有編寫ViewControllerA的代碼,因此您不知道ViewControllerA的生命週期。在呈現視圖控制器ViewControllerB之後,它可能會消除5秒(說)。在這種情況下,如果您僅僅使用ViewControllerB中的dismissViewController來解除它自己,那麼您最終會處於未定義狀態 - 可能不是崩潰或黑屏,而是從您的角度來看,它是一個未定義的狀態。

如果您使用委託模式,那麼您應該瞭解ViewControllerB的狀態,並且可以編寫一個類似於我所描述的案例的程序。

0

斯威夫特

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

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