iOS在segue过渡到另一个视图时如何传递值

27

我试图做一件在许多地方都有记录的事情,但似乎无法控制。我正在尝试在 segue 过程中从一个视图传递数据到另一个视图。

这是源视图中的 prepareForSegue 方法:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{

    //pass values
DetailViewController *dest = (DetailViewController *)[segue destinationViewController];

dest.locTitle = [value valueForKeyPath:@"title"];
dest.locInfo = [value valueForKeyPath:@"info"];



// NSLog(@"The title is: %@, and the info is: %@.",dest.locTitle,dest.locInfo);

}

如果我启用那个最后的NSLog,我会看到正确的值...

这是目标视图上的接口:

#import <UIKit/UIKit.h>

@interface DetailViewController : UIViewController{

}

@property (strong, nonatomic) NSString *locTitle;
@property (strong, nonatomic) NSString *locInfo;
@property (weak, nonatomic) IBOutlet UILabel *detailMainText;
@property (weak, nonatomic) IBOutlet UILabel *detailTitle;

@end

这里是viewDidLoad和目标视图相关的@synthesize:

@synthesize detailMainText,detailTitle,locTitle,locInfo;

- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(@"In viewDidLoad - the title is: %@ and the info is: %@",self.locTitle,self.locInfo);
detailTitle.text = locTitle;
detailMainText.text = locInfo;
}

那个NSLog 报告了这些变量每一个的null值。

我会非常感激您能够给我任何帮助。我相信我做了一些愚蠢和显然的事情。

感谢您提前的帮助。


很久以后...


好的...我想我正在缩小范围。

我发现这样做(违反直觉)

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

之后被调用

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

这让我感到困惑,也破坏了我的小计划,即确定应该在我的详细视图中显示的NSDictionary数据源的哪个块。目前我正在执行以下操作:

// send info to detail view according to which row selected
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {

    //Get the selected object in order to fill out the detail view
    myValue = [myLocations objectForKey:[locationsIndex objectAtIndex:indexPath.row]];

}

但是,由于这发生在segue之后,所以它有点无用。我如何在prepareForSegue方法中访问行号?

再次感谢。


... 最后 ...


以下是问题的答案:

在prepareForSegue方法中如何访问所选行的行号?

希望对某人有用。

首先,在listView控制器的界面中为tableview设置一个IBOutlet

@property (weak, nonatomic) IBOutlet UITableView *tableView;

那么你的 prepareForSegue 可以这样做:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString: @"showDetail"]) {
    //pass values
    NSLog(@"The sender is %@",sender);

    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
    //Get the selected object in order to fill out the detail view
    id myValue = [myLocations objectForKey:[locationsIndex objectAtIndex:indexPath.row]];

    DetailViewController *dest = [segue destinationViewController];
    dest.locTitle = [myValue valueForKeyPath:@"title"];
    dest.locInfo = [myValue valueForKeyPath:@"info"];

    //NSLog(@"The title is: %@, and the info is: %@.",dest.locTitle,dest.locInfo);
}
}

不,我想现在可能更接近了,但我遇到了“嵌套推送动画可能导致导航栏损坏”的问题。 - james Burns
4
是的,也许可以!如果您有一个从单元格开始的转场,那么您不需要在didSelectRow中“手动”调用它。您可能会收到两个调用的segue,导致混淆。请从didSelectRow中删除您的代码- segue是否仍然执行? - jrturton
如果segue从一个视图控制器对象到下一个视图控制器对象,则需要手动执行segue。如果segue来自UI元素,则在点击该元素时会自动执行。 - jrturton
你真是个天才。这解决了“嵌套”问题。现在我只有传递“晚”的值的问题。也就是说 - segue触发后,视图显示出来时UILabels填充为nil,但如果我使用导航返回到列表,然后再次点击列表项,我发现UILabels已经填充为我上次点击的最后一个值(从第一个segue)。我传递它们时肯定出了问题。尝试过viewDidLoad和ViewWillAppear。行为相同。 - james Burns
哈哈,干得好。如果我在场的话,我会建议你这样做的。你应该把这个作为答案发布,并在允许的时候接受它(我记不清时间限制是多久了,24小时还是什么?) - jrturton
显示剩余4条评论
5个回答

11

你可以通过以下方式实现:首先在此处传递要发送到目标控制器的值:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     [self performSegueWithIdentifier:@"segueToLocation" sender:the object you want to pass];
}

然后在这里获取对象

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString: @"segueToLocation"]) {    
         DetailViewController *dest = (DetailViewController *)[segue destinationViewController];
         //the sender is what you pass into the previous method
         dest.target=sender
    }
}

4

您不需要创建目标视图控制器的本地实例变量。以下代码将产生相同的效果:

[segue.destinationViewController setLocTitle: [myValue valueForKeyPath:@"title"];
[segue.destinationViewController setLocInfo: [myValue valueForKeyPath:@"info"];

1
我认为我曾经遇到完全相同的问题,所以希望我的解决方案也能帮助你。它应该回答了你问题的第一部分,或者至少会帮助其他人。
首先,在SecondViewController中不能使用viewDidLoad方法将传递的值分配给属性。这样做会导致返回nil,因为viewDidLoad在Segue之前实现。
而且我不建议使用viewDidAppear,因为值将在视图加载后更改,这使得更改过程在视觉上可见。
因此,最好的选择是直接将值分配给IBOutlet's。 如果您想传递一个字符串数组,可以分配一个要加载的数组值,并传递所有NSArray。这将允许您的视图已经加载了该值,同时您还可以使用其他值进行操作。
您还可以调用方法并传递数据。

1
另一个选项 - 可以使用以下方法:

{{link1:-(NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath :(NSIndexPath *)indexPath}}

在 prepareForSegue 之前触发。


1
你可以尝试这个:
[[NSString alloc] initWithFormat:@"%@",
  [segue.destinationViewController setLocTitle: [myValue valueForKeyPath:@"title"]];
[[NSString alloc] initWithFormat:@"%@",
  [segue.destinationViewController setLocTitle: [myValue valueForKeyPath:@"info"]];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接