问题
在ViewController之前传值分为两种情况:
- 向前传值。
- 向后传值。
例如我们的项目中有两个ViewController,分别为ViewControllerA(以下简称A)和ViewControllerB(以下简称B),A打开了B,B需要一个参数用来初始化,那么A就要提供这个参数,这种情况就是向前传值,代码如下:
//this happens in ViewControllerA
ViewControllerB*viewControllerB = [[ViewControllerB alloc]init];
viewControllerB.initValue = @"initValue";
[self.navigationController pushViewController:viewControllerB animated:YES];
A打开B是有自己的目的的,他需要B根绝相关参数或者服务器端的返回值提供一个结果,然后使用这个结果做一些事情,这种情况就是向后传值。
办法
向前传值
处理向前传值有两种情况,第一种,使用代码打开的方式,这种情况下只需将需要初始化的值声明在B的头文件中,然后在A中对其进行赋值即可(即以上代码)。第二种,使用StoryBoard打开,这种情况需要采用以下代码赋值,不过仍然在B的头文件中声明
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
ViewControllerB *viewControllerB = (ViewControllerB *)segue.destinationViewController;
controller.initValue = @“hi”;
}
}
//如果ViewControllerB是包裹在NavigationController中的,需要稍微改下代码
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:@"showDetailSegue"]){
UINavigationController *navigationController = (UINavigationController *)segue.destinationViewController;
ViewControllerB *viewControllerB = (ViewControllerB *)navController.topViewController;
controller.initValue = @“hello”;
}
}
向后传值
代码块
向后传值可以采用两种方式,代码块和代理模式。以下代码为使用代码块的方式:
首先在ViewControllerB的头文件(.h)中声明代码块
//ViewControllerB.h
@interface ViewControllerB : UIViewController
@property (nonatomic, copy) void (^completion) (NSInteger, id);
...
@end
然后在ViewControllerA中给代码块赋值
//ViewControllerA.m
ViewControllerB*viewControllerB = [[ViewControllerB alloc]init];
viewControllerB.initValue = @"initValue";
viewControllerB.completion = ^(NSInteger resultCode, id data) {
if (resultCode == 0) {
//Maybe you should check if data is kind of dictionary
NSDictionary*dictionary = data;
//do the work
...
}
};
[self.navigationController pushViewController:viewControllerB animated:YES];
最后在关闭ViewControllerB之前提供结果即可
//ViewControllerB.m
self.completion (0, @{@"key":@"value"});
[self.navigationController popViewControllerAnimated:YES];
代理模式
以下代码为使用代理模式的方式
首先在ViewControllerB的头文件(.h)中声明协议和代理属性
//ViewControllerB.h
@protocol ViewControllerCompleteDelegate <NSObject>
@required
- (void)complete:(NSInteger)requestCode result:(NSInteger)resultCode data:(id)data;
@end
@interface GenderViewController : UIViewController
@property (nonatomic, strong) id<ViewControllerCompleteDelegate> completeDelegate;
...
@end
然后在ViewControllerA中实现协议并给代理属性赋值
//ViewControllerA.m
@interface ViewControllerA ()<ViewControllerCompleteDelegate>
...
@end
//实现协议
- (void)complete:(NSInteger)requestCode result:(NSInteger)resultCode data:(id)data {
NSLog (@"the result is %@", data);
}
ViewControllerB*viewControllerB = [[ViewControllerB alloc]init];
viewControllerB.initValue = @"initValue";
genderVC.completeDelegate = self;
[self.navigationController pushViewController:viewControllerB animated:YES];
最后在关闭ViewControllerB之前提供结果即可
//ViewControllerB.m
[self.completeDelegate complete:0
result:0
data:@{@"key":@"value"}];
[self.navigationController popViewControllerAnimated:YES];