StoryBoard使用之页面传值

最近接手一个半成品的项目,由于前期另一位iOS开发的同事使用的StoryBoard(简称SB)搭建的框架,接手后就继续使用SB开发。之前项目一直使用纯代码和xib来做UI,对于SB用起来还觉得挺麻烦,虽然可视化界使层次结构更加清晰,但是对于一个UI简单和大量页面复用的项目,使用SB反而降低了效率。刚好这个项目就是UI简单和大量页面复用,SB对这个项目来说只是展示结构的作用,由于很多复用界面导致SB看起来像蜘蛛网一样混乱,完全掩盖了SB的设计初衷吧,并且SB上大部分ViewController只是展示作用并没有发挥提高界面绘制的优势,反而在创建页面、跳转页面的时候降低开发效率。既然项目利用到了,下面就说说使用segue跳转界面传值的几种方法。

方法一: 设置一个局部变量保存要传数据

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
ProjectItem *item = dataAry[indexPath.row];
projectId = item.projectId;
[self performSegueWithIdentifier:@"detailSegue" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[ViewController class]]) {
ViewController *controller = segue.destinationViewController;
controller.projectId = projectId;
}
}

方法二: 在prepareForSegue:sender:使用indexPathForSelectedRow获取目标控页面所需参数

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:@"detailSegue" sender:self];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[ViewController class]]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ProjectItem *item = dataAry[indexPath.row];
ViewController *controller = segue.destinationViewController;
controller.projectId = item.projectId;
}
}

方法三: 使用performSegueWithIdentifier:sender:方法的sender传递目标页面所需数据

推荐使用此方法,其他UI控件事件也同样适用

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:@"detailSegue" sender:indexPath];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[ViewController class]]) {
NSIndexPath *indexPath = (NSIndexPath *)sender;
ProjectItem *item = dataAry[indexPath.row];
ViewController *controller = segue.destinationViewController;
controller.projectId = item.projectId;
}
}

不推荐使用此方法

1
2
3
4
5
6
7
8
9
10
11
12
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
ProjectItem *item = dataAry[indexPath.row];
[self performSegueWithIdentifier:@"detailSegue" sender:item.projectId];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[ViewController class]]) {
ViewController *controller = segue.destinationViewController;
controller.projectId = sender;
}
}

总结

  • 方法一使用起来比较麻烦,需要额外的创建一个成员变量来存值,但是可以应用到任何具有点击事件的方法中;
  • 方法二局限于UITableView,若同时使用deselectRowAtIndexPath:indexPath animated:也将会使使用此方法后indexPathForSelectedRow方法无法获取indexPath;
  • 方法三中sender就是发送器的意思,也就是用于接收存储发送器。id类型是不确定类型,虽然可以用于传各种参数,但是根据sender的意思最好设置为发送器。