2013-07-01 96 views
6

我最近經常使用容器VC,我一直在想,主VC和容器VC之間的最佳通信方式是什麼。現在即時通知使用,但我寧願使用更好的東西。我如何獲得一個指向容器VC的指針,以便至少可以使用委派?有更好的方法嗎?什麼是與容器視圖溝通的最佳做法

+0

您是否正在使用容器視圖和嵌入式Segue的故事板,或者您是否在代碼中創建和連接視圖控制器? –

+0

Vc內有一個容器。使用故事板 –

回答

22

容器視圖控制器在它的prepareForSegue:sender:方法中建立它自己和嵌入式視圖控制器之間的任何必要連接。

在iOS編程中,我們有這種風格的視圖控制器之間的通信模式。你可以在「Coordinating Efforts Between View Controllers」 in the *View Controller Programming Guide for iOS」中看到它。

但我認爲用一個具體的例子來理解起來會更容易。讓我們用谷歌地圖應用的iPhone:

Google Maps app for iPhone

我不知道這個程序究竟是如何實現的。但假設有一個頂級AppViewController管理搜索欄(位於頂部)和位置欄(位於底部),它將MapViewController嵌入到容器視圖中。

視圖控制器之間存在一些交互。當用戶搜索時,AppViewController需要告訴MapViewController放置一些地圖標記並放大其中的一個。當用戶點擊地圖標記時,MapViewController需要告知AppViewController在底部的地址欄中顯示有關該標記的信息。

所以這裏的模式。

首先,我們定義爲消息的協議,該MapViewController(其嵌入視圖控制器)將發送到AppViewController(它是容器視圖控制器):

@class MapMarker; 
@class MapViewController; 

@protocol MapViewControllerDelegate <NSObject> 

- (void)mapViewController:(MapViewController *)mapViewController didSelectMarker:(MapMarker *)marker; 

@end 

我們將使AppViewController符合這個協議。所以MapViewController不需要特別知道AppViewController。它只需要引用一些符合協議的對象。 MapViewController還需要了解設置其標記和放大到特定標記的消息的消息。因此,我們宣佈MapViewController這樣的:

@interface MapViewController : UIViewController 

@property (nonatomic, weak) id<MapViewControllerDelegate> delegate; 

- (void)setMarkers:(NSArray *)markers; 
- (void)zoomToMarker:(MapMarker *)marker; 

@end 

注意,delegate屬性是weak避免保留週期。

AppViewController需要符合MapViewControllerDelegate協議。通常,我們在AppViewController.m的類擴展中聲明該一致性,因爲一致性不需要是AppViewController的公共接口的一部分。 AppViewController也需要參考MapViewController

@interface AppViewController() <MapViewControllerDelegate> 

@property (nonatomic, strong) MapViewController *mapViewController; 

@end 

接下來,我們進入故事板,選擇嵌入SEGUE,並給它一個標識符:

embed segue identifier

現在我們可以實現prepareForSegue:sender:方法要連接的屬性:

@implementation AppViewController 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    if ([segue.identifier isEqualToString:@"MapEmbedding"]) { 
     [self prepareForMapEmbeddingSegue:segue sender:sender]; 
    } 
} 

- (void)prepareForMapEmbeddingSegue:(UIStoryboardSegue *)segue sender:(id)sender { 
    self.mapViewController = segue.destinationViewController; 
    self.mapViewController.delegate = self; 

    // We can do any additional setup on mapViewController here, 
    // like set its initial viewport. 
} 

請注意AppViewController也必須執行mapviewController:didSelectMarker:MapViewController需要執行setMarkers:zoomToMarker:

+0

哇,很好的回答! – woobione

相關問題