通过storyboard和xcode正确创建手动segue [英] Creating manual segue correctly through storyboard and xcode

查看:550
本文介绍了通过storyboard和xcode正确创建手动segue的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对xcode很新,我正在尝试开发一个基本上是嵌入式tableview的示例应用程序,它有很多级别。我有一个plist存储每个tableview的单元格。如果细胞没有孩子,那么我希望能够在按下细胞后进入一个详细视图。最终,我希望能够根据数据类型转到不同的详细视图。为此,我从故事板创建了一个详细视图,将我的视图控制器拖到我的详细视图中以创建手动推segue,并将segue标记为segue1。

I'm quite new to xcode, and I am trying to develop a sample app that is basically an embedded tableview which has many levels. I have a plist which stores the cells of each tableview. If the cells do not have children, then I want to be able to go to one detailed view once the cell is pressed. Eventually I want to be able to go to different detailed views depending on data type. To do this, I created a detailed view from storyboard, dragged my view controller to my detailed view to create a manual "Push" segue, and labeled the segue "segue1".

编辑:源代码这里

接下来我填充我认为必要的功能,即调用 [self performSegueWithIdentifier :@segue1sender:myString]; 其中myString是我选择的单元格的标题。

Next I populate what I assumed to be the necessary functions for this to work, which is to call [self performSegueWithIdentifier:@"segue1" sender:myString]; where myString is the title of the cell I selected.

- (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;

    }

}

最后,我调用为segue做准备,寻找标记为segue1的segue。

Finally, I called prepare for segue which looks for the segue labeled 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:@segue1sender:myString]; 时,它就会出现错误

I thought this would work, but for some reason, whenever the code reaches [self performSegueWithIdentifier:@"segue1" sender:myString];, it breaks with the error

*****由于未捕获的异常'NSInvalidArgumentException'终止应用程序,原因:'Receiver()没有带标识符'segue1'的segue''
*第一次抛出调用堆栈:
(0x14b4022 0xeb4cd6 0xdf61b 0x3590 0xa85c5 0xa87fa 0x93d85d 0x1488936 0x14883d7 0x13eb790 0x13ead84 0x13eac9b 0x139d7d8 0x139d88a 0x17626 0x23ed 0x2355 0x1)
终止称为抛出异常(lldb)

***** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver () has no segue with identifier 'segue1'' * First throw call stack: (0x14b4022 0xeb4cd6 0xdf61b 0x3590 0xa85c5 0xa87fa 0x93d85d 0x1488936 0x14883d7 0x13eb790 0x13ead84 0x13eac9b 0x139d7d8 0x139d88a 0x17626 0x23ed 0x2355 0x1) terminate called throwing an exception(lldb)

I无法弄清楚为什么它告诉我它已经在故事板和代码中定义时找不到segue1。

I can't figure out why it's telling me it can't find segue1 when it's already defined in storyboard and the code.

推荐答案

实际上有几个问题:

首先,在您上传给我们的项目中,segue 承担seg ue1identifier:

First, in that project you uploaded for us, the segue does not bear the "segue1" identifier:

如果您尚未填写该标识符,则应填写该标识符。

You should fill in that identifier if you haven't already.

第二,当您从表视图推送到表视图时,您正在调用 initWithNibName 创建一个视图控制器。你真的想使用 instantiateViewControllerWithIdentifier

Second, as you're pushing from table view to table view, you're calling initWithNibName to create a view controller. You really want to use 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];
    }
}

它应该简化以消除对<$的引用c $ c> visibleViewController ,例如:

And it should be simplified to eliminate reference to visibleViewController, e.g.:

-(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为您合成标准setter),然后将 viewDidLoad 更改为如下所示:

There are a bunch of problems here, but you simply should not be updating the label.text here (because it might not yet be created!). You should just eliminate this custom setter method completely (just let Xcode synthesize the standard setter for you) and just change your viewDidLoad to read as follows:

- (void)viewDidLoad
{
    [super viewDidLoad];

    label.text = self.itemName;
}

确保在之前不更新UI对象viewDidLoad

我没有完成整个程序,但通过这四个更正,我可以点击SubItem1,然后汽车,然后宝马,我看到一个详细的屏幕,上面写着宝马。我认为你的plist在其他项目上存在一些问题(例如鞋子条目是字符串,而不是字典条目,你得到一个错误......我猜你还没有完全填写你的plist),但上面的修正纠正更重要的编码问题。

I haven't gone through the whole program, but with those four corrections I can tap on "SubItem1", and then "Cars", and then "BMW" and I see a detail screen that says "BMW". I think there are some problems with your plist on other items (e.g. the shoes entries are strings, and not dictionary entries and you get an error ... I presume you just haven't filled in your plist completely), but the above fixes correct the more significant coding issues.

这篇关于通过storyboard和xcode正确创建手动segue的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆