2012-09-20 73 views
18

我對xcode很陌生,我正在嘗試開發一個示例應用程序,它基本上是一個嵌入式tableview,它有很多級別。我有一個plist存儲每個tableview的單元格。如果細胞沒有孩子,那麼一旦細胞被按下,我希望能夠進入一個詳細的視圖。最終,我希望能夠根據數據類型轉到不同的詳細視圖。爲此,我創建了故事板的詳細視圖,將我的視圖控制器拖到我的詳細視圖中,以創建手動「推」漸變,並將其標記爲「segue1」。通過故事板和xcode正確創建手動segue

編輯:源代碼here

Building Manual Segue

接下來,我填寫了我認爲是必要的功能,這個工作,這是調用[self performSegueWithIdentifier:@"segue1" sender:myString];,其中MyString的是電池我的標題選擇。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    //Check the dictionary to see what cell was clicked 
    NSDictionary *dict = [self.tableDataSource objectAtIndex:indexPath.row]; 
    NSString *myString = [dict objectForKey:@"Title"]; 
    NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row]; 

    NSArray *children = [dictionary objectForKey:@"Children"]; 

    //If there is no children, go to the detailed view 
    if([children count] == 0) 
    { 
     [self performSegueWithIdentifier:@"segue1" sender:myString]; 

    } 
    else{ 
     //Prepare to tableview. 
     DrillDownViewController *rvController = [[DrillDownViewController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]]; 

     //Increment the Current View 
     rvController.CurrentLevel += 1; 

     //Set the title; 
     rvController.CurrentTitle = [dictionary objectForKey:@"Title"]; 

     //Push the new table view on the stack 
     [self.navigationController pushViewController:rvController animated:YES]; 

     rvController.tableDataSource = children; 

    } 

} 

最後,我打電話給準備for segue尋找segue標籤segue1。

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if([[segue identifier] isEqualToString:@"segue1"]) 
    { 
     DrillDownDetailController *dvController = [[segue destinationViewController] visibleViewController]; 
     //DrillDownDetailController *dvController = [[DrillDownDetailController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]]; 
     [dvController setItemName:(NSString *)sender]; 
     [self.navigationController pushViewController:dvController animated:YES]; 
    } 
} 

我想這會工作,但由於某種原因,每當代碼達到[self performSegueWithIdentifier:@"segue1" sender:myString];,它與錯誤

*****打破終止應用程序由於未捕獲的異常「NSInvalidArgumentException」,究其原因: '接收器()具有標識符沒有賽格瑞 'segue1'' *第一擲調用堆棧: (0x14b4022 0xeb4cd6 0xdf61b 0x3590 0xa85c5 0xa87fa 0x93d85d 0x1488936 0x14883d7 0x13eb790 0x13ead84 0x13eac9b 0x139d7d8 0x139d88a 0x17626 0x23ed 0x2355爲0x1) 終止稱爲拋出異常(LLDB )

我不明白爲什麼它告訴我,它已經定義在故事板和代碼中時找不到segue1。

+1

我可能會在這裏完全關閉,因爲我沒有使用segues,但嘗試聲明'DrillDownDetailController * dvController'作爲實例變量,然後在'prepareForSegue'中設置您需要在VC上的任何屬性。不要把風險投資推到海軍控制員身上,然後再進行調整。 – mkral

+0

@mkral你能否詳細說明「不要把VC推到海軍控制員的準備中,然後再進行調整」?因此,刪除pushViewController行並將該行放入新的performSegue函數中? – foboi1122

+0

我會添加一個格式化的答案。如果它不起作用希望別人能來 – mkral

回答

23

幾個問題代碼中的註釋,實際上是:

首先 ,在你上傳的那個項目中,segue確實是不是帶有「segue1」標識符:

no identifier

如果您尚未填寫該標識符,請填寫該標識符。

第二個,當您從表視圖推送到表視圖時,您打電話initWithNibName來創建視圖控制器。你真的想用instantiateViewControllerWithIdentifier

因此,該行稱:

DrillDownViewController *rvController = [[DrillDownViewController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]]; 

應該說:

DrillDownViewController *rvController = [self.storyboard instantiateViewControllerWithIdentifier:@"TableView"]; 

,您prepareForSegue是:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if([[segue identifier] isEqualToString:@"segue1"]) 
    { 
     dvController = [[segue destinationViewController] visibleViewController]; 
     [dvController setItemName:self->nameToSend]; 
    } 
} 

它應該被簡化,消除參考visibleViewController,例如:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if([[segue identifier] isEqualToString:@"segue1"]) 
    { 
     dvController = segue.destinationViewController; 
     dvController.itemName = nameToSend; 
    } 
} 

,你DrillDownDetailController.m有這個方法:

-(void) setItemName:(NSString *)itemName 
{ 
    if(!itemName) 
    { 
     itemName = [[NSString alloc] initWithString:itemName]; 
    } 
    label.text = itemName; 
} 

還有一堆的問題在這裏,但你根本不應該在這裏更新label.text(因爲它可能尚未被創建!)。你應該消除這種定製的setter方法完全(只是讓Xcode中合成的標準制定者你),只是改變你的viewDidLoad,內容如下:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    label.text = self.itemName; 
} 

確保您不更新UI對象,直到viewDidLoad

我還沒有經歷過整個程序,但有了這四個更正,我可以點擊「SubItem1」,然後「汽車」,然後「寶馬」,我看到一個詳細的屏幕顯示「寶馬」。我認爲你的plist在其他項目上存在一些問題(例如鞋子條目是字符串,而不是字典條目,並且你得到一個錯誤......我認爲你只是沒有完全填充你的plist),但上述修復糾正更重要的編碼問題。

+1

感謝您的輸入!我已經解決了我的問題 – foboi1122

2

主要的問題是在這裏,你正在創建一個空白DrillDownViewController,不重用從故事板的一個,見下面

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    { 
     if([[segue identifier] isEqualToString:@"segue1"]) 
     { 
      [segue.destinationViewController setItemName:(NSString*)sender]; 
     } 
    } 

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
     //Check the dictionary to see what cell was clicked 
     NSDictionary *dict = [self.tableDataSource objectAtIndex:indexPath.row]; 
NSString *titleName = [dict objectForKey:@"Title"]; 
NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row]; 

NSArray *children = [dictionary objectForKey:@"Children"]; 

if([children count] == 0) 
{ 
    [self performSegueWithIdentifier:@"segue1" sender:titleName]; 

} 
     else{ 
    //Prepare to tableview. 

    //THE MAIN ISSUE IS HERE, you were creating a blank DrillDownViewController, not reusing the one from storyboards so it did not have a segue at all defined. instead do this: 
    UIStoryboard* sb = [UIStoryboard storyboardWithName:@"MainStoryboard" 
                bundle:nil]; 
    DrillDownViewController *rvController = [sb instantiateViewControllerWithIdentifier:@"DDVC"];  
    //Increment the Current View 
    rvController.CurrentLevel += 1; 

    //Set the title; 
    rvController.CurrentTitle = [dictionary objectForKey:@"Title"]; 

    //Push the new table view on the stack 
    [self.navigationController pushViewController:rvController animated:YES]; 

    rvController.tableDataSource = children; 

} 


    } 
+0

你可以通過發件人發送NSString嗎?或者那是皺起了眉頭。大部分時間我看到發件人:自我,但我沒有看到在代碼中發件人的任何引用,所以我認爲我可以發送任何我想要的發件人 – foboi1122

+0

我其實不確定,但我不'不要以爲你應該,而應該發送被單擊的單元格,然後在prepareForSegue中獲取字符串。 – mkral

+0

,因爲在這種情況下,點擊的按鈕/單元是發送者。 – mkral