2012-09-20 50 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