2012-08-05 50 views
0

我的根控制器是一個帶有靜態單元和導航控制器的TableViewController。 取決於選擇哪個單元格,我想推入另一個ViewController(帶有嵌入的TableView),它將相應地更改其配置(啓用或不啓用按鈕,來自db表或NSArray的單元格數據等)。 選擇一些「控制器A」單元將調用「控制器B」或「控制器C」並傳遞一些數據。在視圖控制器之間移動並傳遞數據的正確方法

的代碼我想看起來像這樣:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    switch (indexPath.row) { 
     case 0: 
     { 
      [self performSegueWithIdentifier:@"segueToType" sender:self]; 
     } 
      break; 
     case 1: 
     { 
      [self performSegueWithIdentifier:@"segueToType" sender:self]; 
     } 
} 
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 

if ([[segue identifier] isEqualToString:@"segueToType"]) 
{ 
    NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow]; 
    NSInteger rowNumber = selectedIndexPath.row; 
    switch (rowNumber) { 
     case 0: 
     { 
      TypeSelectController *selCon = [segue destinationViewController]; 
      selCon.myPet = self.myPet; 
      selCon.sel = @"tipo"; 
      selCon.delegate = self; 
     } 
      break; 
     case 1: 
     { 
      TypeSelectController *selCon = [segue destinationViewController]; 
      selCon.myPet = self.myPet; 
      selCon.sel = @"razza"; 
      selCon.delegate = self; 
     } 
      break; 
     default: 
      break; 
    } 

} 
} 

在這種情況下,例如,我只調用「控制器B」,但根據的「控制器A」選中單元格上它以不同的方式配置自己(取決於「selCon.sel」字符串)。

在「控制器B」,我有這樣的代碼:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
if ([sel isEqualToString:@"tipo"]) { 
    NSString *itemToPassBack = [tipi objectAtIndex:indexPath.row]; 
    [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack ofType:@"tipo"]; 
    [self.navigationController popViewControllerAnimated:YES]; 
} else if ([sel isEqualToString:@"razza"]) { 
    NSString *itemToPassBack = [razze objectAtIndex:indexPath.row]; 
    [self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack ofType:@"razza"]; 
    [self.navigationController popViewControllerAnimated:YES]; 
} 
} 

如此反覆,這取決於字符串「SEL」值,我返回不同的數據,「控制器A」。

當我選擇控制器A中的第一個單元格時,我正確得到了控制器B的場景。然後我選擇一個單元並返回到控制器A並輸入正確的數據。 現在,如果我嘗試選擇控制器A的第二個單元格,選擇在控制器B細胞,導航不迴應,因爲我想和我得到的控制器C情景,那麼控制器A和以下錯誤:

嵌套的推動動畫可能導致導航欄損壞

完成處於意外狀態的導航轉換。導航欄子視圖樹可能會損壞。

不平衡呼叫開始/結束外觀轉換。

我在做什麼錯?

+0

我不確定是否有足夠的代碼來幫助您。你有什麼好看的,除了你在用這行做什麼:[self.delegate addItemViewController:self didFinishEnteringItem:itemToPassBack ofType:@「razza」];我不明白在addItemViewController委託調用中傳遞自己。你是否注入到視圖控制器或導航流? – CocoaEv 2012-08-05 17:15:32

+0

這是使用委託方法將數據傳回控制器A所需的代碼的一部分。我用這個鏈接顯示的代碼:http://stackoverflow.com/questions/5210535/passing-data-between-view-controllers – Aleph72 2012-08-05 17:25:57

+0

這個例子在理論上是好的,但當你使用故事板和segues時不適合。你需要做什麼「物品回傳?」 - 特別是在使用協議和委託時,您通常會設置一個屬性或將屬性傳遞給原始vc。我會爲你寫一個答案。 – CocoaEv 2012-08-05 17:38:14

回答

0

OK,再次嘗試這個。

  • 讓我們用髮色的例子。你在控制器a中有一張桌子,裏面有一個用於染髮的靜態細胞。可以說你顯示了所選顏色的文本值。 cell.textLabel = self.hairColor。如果它是空白的,用戶可以觸摸單元並打開一個新的控制器來選擇顏色。
在你segue'd新的視圖控制器

,你設置一個屬性來告訴它來查找「hairColor的」。因此,建立一個列表從一個數據庫稱爲listOfHairChoices。

用戶選擇self.delegate.hairColor = [self.listOfHairChoices objectAtIndex:indexPath.row]; 然後彈出關閉子vc並彈出回到父。[第一行,其中,所以你使用你的委託引用這樣設置屬性。 self.navigationController popViewCon..etc]

然後回到父級,在 - (void)viewDidAppear你剛剛重新加載你的tableview像這樣:[self.tableV查看數據]

現在,您的原始tableview應顯示在子視圖控制器中選擇的單元格的值。

這是一種直接的做法,每一步都需要邏輯來確定您正在使用哪個屬性以及需要設置哪些屬性 - 但可以與現有框架一起使用。

另一種方法是創建您正在呈現的數據的模型類,然後將該模型傳遞給子VC--讓他們更新模型並將其傳回,然後在更新後的模型中簡單地重新加載表每個轉換。你可能並不熟悉這種方法,但它可以簡化事物並減少你現在對於tableview每一行的所有條件邏輯。

希望這個建議可以幫助您完成您的項目。

+0

我已經有一個模型類,所以我認爲我做的事情比我應該做的更多。今晚晚些時候,我會根據你所說的話讓你知道一些變化。現在非常感謝你們的幫助。 – Aleph72 2012-08-05 18:41:45

+0

好吧我正在嘗試模型類的方法。我已經將我的模型類(myPet)的實例發送給子VC。然後在那個VC中,我可以根據選擇哪個單元簡單地更新模型。現在我對如何將更新後的模型發送回父VC表示懷疑。 – Aleph72 2012-08-05 19:35:09

+0

好吧,我做到了。我不必做任何奇怪的事情來傳回更新的模型。我只是在孩子VC中更新它,然後彈出它。重新加載父VC中的tableview顯示更新的數據。導航變得瘋狂的問題似乎已經解決了。我將這個答案標爲正確答案,即使你們兩人都幫了我很多。再次感謝。 – Aleph72 2012-08-05 20:25:53

0

在故事板示例中使用協議和委託的快速示例。只是在這裏突出亮點,因爲你已經是最重要的了。

控制器a(父)具有一個名爲category的NSString屬性和一個名爲partNumber的控件。有一個桌面視圖。選擇行以啓動賽格。 [self performSegueWithIdentifier:@「segueToType」sender:self];

  • (無效)prepareForSegue:(UIStoryboardSegue *)賽格瑞發件人:(ID)發送方 {

如果([[賽格瑞標識符] isEqualToString:@ 「segueToType」]) {
ControllerB * b = segue.destinationViewController; b.category = self.category; b.delegate = self; }

視圖控制器B

@protocol - (無效)doSomethingWithPickedPartNumber:(的NSString *)部分號碼; @end

//設置tableview與傳入類別的partnumbers。

// row selected,so we have partNumber we want to send back。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
NSString *pn = [self.listOfParts objectAtIndex:indexPath.row]; 

//options - set the variable in the parent or call a method in the parent 
self.delegate.partNumber = pn; 
//if you set the variable in the parent - you can check for it in the -(void)viewWillAppear method and reconfigure the parent view if needed 

//or do this 
[self.delegate doSomethingWithPickedPartNumber:pn]; 

//this is actually calling a method in the parent. remember you don't have a view you can see yet, but its in memory and you can modify things so when the child pops back it will look how you want it. Also note, you can name the protocol methods what ever you want, as long as they match up from the parent to the protocol in the child. 


//then return to parent 
[self.navigationController popViewControllerAnimated:YES]; 

}

相關問題