2011-11-20 80 views

回答

75

正如迦勒和馬特的答案組合的東西,我所做的:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    if ([segue.identifier isEqualToString:@"cpdc_check_embed"]) { 
     self.checkVC = segue.destinationViewController; 
    } 
} 

...其中checkVC是容器控制器的特性:

@property (weak,nonatomic) PXPCheckViewController * checkVC; 

你只需要設置你的embed SEGUE的Storyboard ID到任何你想要的(在這種情況下,cpdc_check_embed):

check embed screen in Xcode

...然後檢查-prepareForSegue:sender:中的標識符。

還沒出口,但比馬特的(恕我直言),比迦勒的更清潔,更具體的,你仍然可以得到一個好看的故事板:

enter image description here

+1

您正在使用嵌入式segue,這是一個iOS 6功能。我的問題從2011年11月開始。:-p –

+0

是的。剛剛意識到我正在讓貓從袋子裏出來一點。試圖安裝到客戶端的5.1.1電話;沒有骰子。 –

+1

現在iOS 6已經發布,這是正確的答案。 – awolf

7

您可以將子視圖控制器與Storyboard中的自定義容器視圖 控制器關聯嗎?

我想你在這裏問的是如何將一個場景中的視圖控制器連接到不同場景中的視圖控制器的出口。我不相信這是可能的,也許是因爲故事板機制可能沒有同時加載故事板中的所有場景。

你可能會問這是因爲你想從一個視圖控制器傳遞一些信息到另一個視圖控制器,從一個場景到下一個場景。當您使用故事板時,執行此操作的方法是在一個或兩個受segue影響的視圖控制器中覆蓋-prepareForSegue:sender:。參數segue中提供的UIStoryboardSegue對象具有sourceViewControllerdestinationViewController屬性,還有identifier屬性。您可以使用這些屬性來識別即將在視圖控制器之間傳輸數據的segue。

雷Wenderlich的博客對使用故事板,可以幫助您一個不錯的兩部分教程:

  • Part 1包括設立一個故事板項目,添加場景,並創造塞格斯。

  • Part 2涉及使用段落在場景之間轉換,包括上述prepareForSeque方法。

的iOS 5允許多個視圖控制器是活躍在同一場景中(儘管仍然應該負責),所以在你的故事板一個場景可能有幾個控制器。您可以使用插座將這些控制器相互連接,並且可以按照您在IB中所做的相同方式配置這些連接:控制 - 在同一場景中從一個控制器拖動到另一個控制器。通常的插座列表將彈出以讓您選擇要連接的插座。

+1

不,我的意思是同時使用兩個視圖控制器。包含多個_child_視圖控制器的_container_視圖控制器。類似於分割視圖控制器,它包含主視圖控制器和詳細視圖控制器,但是分割視圖控制器(父VC)的子項。 –

+3

在這種情況下,只需將NSObject從庫中拖到要包含子視圖控制器的場景的擴展塢中即可。將對象的類型設置爲您的視圖控制器類。之後,您可以通過拖放控件與其他對象(包括場景中的其他視圖控制器)建立連接。如上所述,你不能做的是在不同場景中的對象(視圖控制器或其他)之間建立連接。 – Caleb

+0

因此,與Apple的容器視圖控制器不同,如果我想同時顯示它們,所有視圖控制器(子視圖和父視圖)必須位於同一場景中。那麼,它完成了這項工作,這就是我想要的。謝謝! –

15

故事板非常好地處理內置容器視圖控制器,向子/根視圖控制器顯示segues,以便清晰地顯示關係。兒童和父視圖控制器如何分離成不同的場景也很好。

如果你想在你自己的項目中實現這種效果,那麼有一個技巧並不完美,但非常簡單。在我的例子中,假設我有一個容器視圖控制器,它像一個標籤欄控制器,只有兩個選項卡,'左'和'右'。我想要一個場景表示父視圖控制器,並且兩個單獨的場景表示「左」子視圖控制器和「右」子視圖控制器。

即使這是不可能的,如果我可以在容器視圖控制器中創建IBOutlet到不同場景中的子元素,然後顯示容器視圖控制器時,將會很好設置父/子關係。該規則描述了UIViewController documentation。如果我們引用了我們的'左'和'右'子視圖控制器,那麼我們可以建立關係沒有問題。

此引用問題的標準解決方案是通過將Object出口拖入容器視圖控制器的場景中,然後將它們的類類型指定爲子視圖控制器類的實例來創建對子視圖控制器的引用。

然而,爲了讓孩子們分離出不同的場景,像蘋果的內置容器,我們將使用不同的技巧。首先,假設我們已經在容器類中聲明瞭以下屬性,ContainerViewController

@property (nonatomic, strong, readwrite) UIViewController *leftViewController; 
@property (nonatomic, strong, readwrite) UIViewController *rightViewController; 

在我們的故事板,選擇代表的「左」視圖控制器現場。在屬性檢查器中,將視圖控制器的identifier屬性設置爲"cvc_leftViewController"(「cvc_」指的是ContainerViewController,但確實標識符可以是任何您想要的)。對正確的視圖控制器的場景做同樣的事情,把它的標識符設置爲"cvc_rightViewController"

現在,插入下面的代碼ContainerViewControllerviewDidLoad方法:

if (self.storyboard) { 
    _leftViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"cvc_leftViewController"]; 
    _rightViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"cvc_rightViewController"]; 
} 

ContainerViewController從故事板加載,它會搶‘從各自的場面左’和‘右’視圖控制器和通過其屬性設置對它們的引用。既然您已經控制了子視圖控制器實例,那麼您可以設置父/子關係。要了解如何正確執行此操作,請參閱UIViewController documentation

這個訣竅並不完美,並且有許多警告,但是如果您小心翼翼,您可以使它適合您的項目。

編輯:雖然這是完全不必要的,也不意味着什麼,如果你真的真的希望有孩子的視圖控制器,就像蘋果公司的從你的容器故事板顯示連接內置容器中,就用我的方法,然後在容器場景和子場景之間直接設置segues,並且不要執行那些segues。現在一切都會正常工作,看起來也很漂亮。

+1

+1聽起來是一種很好的技術,你說得對,它模仿了Apple的容器視圖控制器在故事板中的工作方式。與在容器相同的場景中創建子視圖控制器相比,主要缺點是無法在場景之間建立連接。所以,如果你想設置一個子控制器的委託給父控制器,你必須在代碼中這樣做 - 你不能只拖動一個連接。 – Caleb

+1

是的。另外,我總是會因標識符串的連接而感到有些緊張,而不是網點帶來的穩定感。 – Matt

+0

酷黑客!我將在現有的iOS 5應用程序中使用它。我的項目將變得更簡單。蘋果公司解決了我對iOS 6的問題(在Storyboard/IB中有視圖控制器容器視圖),但這是針對新的應用程序,或者當我決定放棄現有應用程序的2-3年的iOS 5時。 –

4

與@問題Ben的(否則合理)答案是它只能在一個嵌套層次上工作。除此之外,它會要求每個後續的VC都被定製以將嵌套視圖控制器保存在prepareForSegue中。

爲了解決這個問題,我花了太多時間去研究一個基於NSObject的索引,你可以添加到Storyboard,綁定到一個場景,然後根據類型和restoreId將它的父VC註冊到全局索引中。這可以工作/可以工作,但最終會付出太多的努力,並且仍然需要兩個步驟來進行可視綁定,並以編程方式查找。

對於我來說,最簡單,最普遍的解決方案是懶洋洋地爬下視圖控制器層次

在我簡單的測試項目中,添加以下行viewDidLoad中:

self.left.data = [ 
     "Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.", 
     "De carne lumbering animata corpora quaeritis." ] 

其中left定義爲:

lazy var left:CollectionViewController = { [unowned self] in 
    return self.childViewControllerWithId("Left") as! CollectionViewController }() 

childViewControllerWithId定義爲:

extension UIViewController { 
    func childViewControllerWithId(rid:String) -> UIViewController? { 

     // check immediate child controllers 
     for vc in self.childViewControllers as! [UIViewController] { 
      if vc.restorationIdentifier == rid { return vc } 
     } 

     // check nested controllers 
     for vc in self.childViewControllers as! [UIViewController] { 
      if let vc = vc.childViewControllerWithId(rid) { 
       return vc 
      } 
     } 

     assert(false, "check your assumptions") 
     return nil 
    } 
} 

請注意,如果需要,您可以根據類型執行其他find變體。另外請注意,上述要求您在Storyboard文件中定義恢復ID。如果你沒有重複實例的視圖控制器,那麼使用類型會更容易。

爲了說明什麼是希望顯而易見的,您不需要執行prepareForSegue,也不必使用延遲加載,您只需致電find(...)即可。

相關問題