2011-12-22 197 views
1

我知道這個話題已經在很多地方被覆蓋了,但是當經歷不同的答案時,我找不到適合我的情況的解決方案。返回一個對象返回到根視圖控制器

基本上什麼,我試圖做的是非常簡單的。我有一個帶有表格視圖的視圖控制器,還有一個+按鈕,用於觸發第二個視圖控制器,用戶可以在其中輸入名稱,然後將該名稱添加到第一個視圖控制器表格視圖中。考慮iPhone上的聯繫人,你可以添加一個新的人(或亞馬遜,你可以添加一個新的信用卡)。

我的問題是 - 什麼是返回此字符串(在這種情況下)回視圖控制器所在的表是最好的方式?

人們使用NSDefaults,委託或單身其中沒有一個是針對這種情況(每一個爲自己的原因),真的好建議。我真的只需要返回一個簡單的字符串。

謝謝你的幫助。

回答

1

這裏就是你需要做什麼(請注意,我打字這個把我的頭頂部,這樣編譯器可能與我的語法一些問題)。

在你的孩子視圖控制器接口:

@protocol ChildDelegate <NSObject> 
- (void)didConfirmName:(NSString*)name 
@end 

@interface ChildViewController : UIViewController 
... 

@property (nonatomic, assign) id<ChildDelegate> delegate; 

和實施,調用的方法中,當用戶確認他們需要什麼,以確認:

- (void)myCustoMethod 
{ 
    ... 
    if ([self.delegate respondsToSelector:@selector(didConfirmName:)]) 
     [self.delegate didConfirmName:NAME_STRING]; 
} 

而在你的父視圖控制器時,您正在實例化子視圖控制器,將SELF指定爲代理人:

ChildViewController *vc = [[ChildViewController alloc] init...]; 
vc.delegate = self; 

並實行:

- (void)didConfirmName:(NSString*)name 
{ 
    // Do whatever you want with the name here... 
} 

另外,還要確保你告訴你正在實現協議編譯:

@interface ParentViewController() <ChildDelegate> 
@end 
+0

*這是唯一「正確」的方式*這是不正確的。有許多有效的方法可以在對象之間共享數據;代表團遠不是唯一「正確」的方式。 – Caleb 2011-12-22 05:05:24

+0

夠公平的,我會編輯我的答案,刪除,因爲你是對的。 – Rog 2011-12-22 05:14:12

1

你不回新事物的TableView中。你需要的是更新爲你的tableView提供信息的來源。
因此,在數據存活的地方,你需要去添加它,當你回到UITableViewController時,你可能需要告訴UITableView它的數據是reload

如果您絕對需要與它溝通,每個UIViewController都有一個句柄。

UIViewController *parentVC = aViewController.parentViewController; 
+0

可以請你提供一個示例代碼?我不清楚我是如何做到這一點的。爲了簡單起見,我們假設在根視圖中沒有表視圖,只是需要更新的簡單字符串。 – TommyG 2011-12-22 03:38:59

+0

試圖,它不起作用。看起來我需要做一些鑄造(見http://stackoverflow.com/questions/956990/accessing-parent-view-controller-custom-properties),這是不能被足夠的方式,因爲我不能似乎能夠將字符串「寫入」回父VC。 – TommyG 2011-12-22 03:55:35

+0

只是要留意,如果你使用的是導航控制器,該'parentViewController'返回將實際導航控制器,而不是以前的視圖控制器。你應該在這個例子中使用委託,這是最簡單也是最正確的。 – Rog 2011-12-22 04:36:04

4

如果從視圖控制器A --->視圖控制器B,在這裏是你的情況下航行,然後你要傳遞的B信息 - > A,則建議使用鬆耦合,像代表團一樣。你討論過的東西有幾個,比如NSUserDefaults,singleton,NSNotification,可能還有更多。

但代表團是更好的和標準的方法來做到這一點。

1

假設需要得到更新的視圖控制器是應用程序的根視圖控制器,可以執行以下操作:

YourViewController * YVC = [(YourAppDelegate *)[[UIApplication的sharedApplication]委託]的viewController];

[YVC updateString:@ 「字符的更新字符串」];

記住:

#import "YourAppDelegate.h" 

但老實說,我會使用委託模式或NSNotification。

+0

這是不正確時,'viewController'方法/屬性甚至不存在用於''。 – Rog 2011-12-22 04:39:00

+1

當然,它不會退出,但通常在應用程序委託你存儲到您的應用程序的RootViewController的一個參考,你可以把它的viewController或任何你想要的...... – Ecarrion 2011-12-22 04:42:41

+0

問題是很多時候根視圖控制器是一個導航控制器,標籤欄控制器等 – Rog 2011-12-22 04:51:50

1

三種佳選擇:

1)具有在第一視圖控制器通本身到第二視圖控制器,使得第二控制器可以將消息發送到所述第一。理想情況下,創建了第一個控制器採用的協議,從而使第二控制器不依賴於第一控制器的類型,但是隻關心它實現的協議:

@protocol Nameable 
@property(copy) NSString* name; 
@end; 

@interface FirstViewController <Nameable> 
//... 
@end 

@implementation FirstViewController 
@synthesize name; 
//... 
@end 

則第一控制器可以做到這一點:

SecondViewController *second = [[SecondViewController alloc] 
initWithNibName:nil]; second.thingToName = self; 
[self.navigationController pushViewController:second animated:YES]; 

而且在時機成熟時,第二控制器可以這樣做:

​​

細節並不真的那麼重要 - 主要的是要知道這裏是如果你想發送消息給一個對象,你首先需要一個指向該對象的指針。當第一個視圖控制器設置second.thingToName = self時,它提供該指針。

2)具有與第一視圖控制器創建數據對象其中第二視圖控制器可以存儲數據,例如:

@interface Person <Nameable> 
//... 
@end 

@implementation Person 
@synthesize name; 
//... 
@end 

現在第一視圖控制器可以創建新的人與通即:

SecondViewController *second = [[SecondViewController alloc] 

Person *person = [[Person alloc] init]; 
[self.people addObject:person]; 
initWithNibName:nil]; second.thingToName = person; 
[person release]; 

[self.navigationController pushViewController:second animated:YES]; 

這類似於第一種方法,只收到所述名字的東西是不是在這裏的視圖控制器,它是某種形式的數據容器(人)。

您也可以在此處看到協議的值 - 請注意,SecondViewController類在第一種方法和第二種方法之間完全不會改變。它不會保護無論是與視圖控制器還是Person或其他實例進行通信......只要該事件實現了可命名協議,就很高興。

3)反轉通信方向。而不是讓第二個視圖控制器發送的字符串,其父得到的字符串。這可能是最簡單的解決方案,但它確實需要父母有一些方法來知道孩子已完成。它會去是這樣的:

@implementation FirstViewController 
//... 

- (IBAction)addNewName:(id)sender 
{ 
    self.secondController = [[SecondViewController alloc] initWithNibName:nil bundle:nil]; 
    [self.navigationController pushViewController:self.secondController animated:YES]; 
} 

- (void)viewWillAppear 
{ 
    if (self.secondController != nil) { // we must be returning from the child 
     self.name = self.secondController.name; 
     self.secondController = nil; 
    } 
} 
@end 
+0

傳遞父視圖控制器其子從來都不是一個好主意,因爲它打破了封裝,它意味着你將不能再使用該子視圖其他地方,因爲它希望傳遞具有某些屬性的控制器。這是協議存在的主要原因之一。 – Rog 2011-12-22 04:40:46

+0

@Rog有什麼都沒有錯父視圖控制器傳遞給孩子。不理想的是讓孩子期待傳遞給父母的東西。你說得對 - 這就是爲什麼我定義了上面命名的協議。爲了清楚起見,我將爲父母添加一個界面,顯示它採用Nameable。 – Caleb 2011-12-22 04:43:59

+0

+1感謝您的幫助。 – TommyG 2011-12-22 05:16:45