在iOS开发新中经常会遇到在两个界面之间进行传值的情况,在页面之间进行数据传递有正向传递(控制器A跳转到控制器B),也有反向传值(控制器B跳转到A).可以通过属性,代理,block,通知等等. 就解释一下怎么使用block和代理进行页面之间反向传值;
使用block进行反向传值 在Xcode中创建新的项目 创建两个控制器A,B. 在A控制器中添加一个按钮,对按钮添加点击跳转到B控制器,然后再A中再次添加一个label,作为接受B控制器中传回来的值. 在B控制器中创建一个UITextField,用于输入信息. 在A控制器中.m文件中代码如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 
 | //// ViewController.m
 // 反向传值
 //
 // Created by 两好三坏 on 16/3/3.
 // Copyright © 2016年 qinakun. All rights reserved.
 //
 import "ViewController.h"
 使用block传值的控制器
 import "BlockVC.h"
 使用delegate传值的控制器
 import "DelegateVC.h"
 @interface ViewController ()
 //用于接受数据的label
 @property (weak, nonatomic) IBOutlet UILabel *inputLabel;
 @end
 @implementation ViewController
 - (void)viewDidLoad {
 [super viewDidLoad];
 }
 //跳转控制器的
 - (IBAction)jumpVC:(id)sender {
 //调用block进行传值
 // [self block];
 //调用bdelegate进行传值
 [self delegate];
 }
 //使用block进行反向传值
 -(void)block{
 UIStoryboard *sb = [UIStoryboard storyboardWithName:@"BlockSB" bundle:nil];
 BlockVC *blockVc = [sb instantiateViewControllerWithIdentifier:@"blockVC"];
 //inputBlock是定义好的block
 [blockVc setInputBlock:^(NSString *string) {
 //在这里对A控制器的label进行设置,这个string参数是从B控制器中传过来的;
 self.inputLabel.text = string;
 }];
 [self.navigationController pushViewController:blockVc animated:YES];
 }
 //使用delegate进行反向传值
 -(void)delegate{
 DelegateVC *vc = [DelegateVC new];
 //需要让控制器A成为控制器B的代理.
 vc.delegate = self;
 [self.navigationController pushViewController:vc animated:YES];
 }
 //代理方法中给input进行传值
 -(void)changeValue:(NSString *)string{
 self.inputLabel.text = string;
 }
 @end
 
 | 
接下来是在控制器B中定义一个block的代码块,这个block的参数是字符串,在控制器B的.h文件中声明如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | @property (nonatomic, copy) void (^inputBlock)(NSString *string);控制器B的.m文件代码如下:
 import "BlockVC.h"
 @interface BlockVC ()
 @property (weak, nonatomic) IBOutlet UITextView *input;
 @end
 @implementation BlockVC
 - (void)viewDidLoad {
 [super viewDidLoad];
 }
 //点击屏幕是输入框失去第一响应者的资格
 -(void)touchesBegan:(NSSet _)touches withEvent:(UIEvent _)event{
 [self.input resignFirstResponder];
 }
 //在控制器即将消失的时候调用,
 -(void)viewWillDisappear:(BOOL)animated{
 [super viewWillDisappear:animated];
 //取到输入框的内容保存在代码块中,在需要的时候将参数传给控制器A
 if (self.inputBlock) {
 self.inputBlock (self.input.text);
 }
 }
 @end
 
 | 
这样就算完成了一个简单的在两个页面之间进行反向传值的功能. 使用delegate进行反向传值 代理应用场景及使用步骤 对象A内部发生了一些事情,想通知对象B 对象B想监听对象A内部发生了什么事情 对象A想在自己的方法内部调用对象B的某个方法,并且对象A不能对对象B有耦合依赖 对象A想传递数据给对象B 以上情况,结果都一样:对象B是对象A的代理(delegate) 1.先搞清楚谁是谁的代理(delegate) 2.定义代理协议,协议名称的命名规范:控件类名 + Delegate 3.定义代理方法 代理方法一般都定义为@optional 代理方法名都以控件名开头 代理方法至少有1个参数,将控件本身传递出去 设置代理(delegate)对象 (比如myView.delegate = xxxx;) 代理对象遵守协议 代理对象实现协议里面该实现的方法 在恰当的时刻调用代理对象(delegate)的代理方法,通知代理发生了什么事情 (在调用之前判断代理是否实现了该代理方法) 这是代理的使用场景以及使用步骤,下面是使用delegate实现前面block实现的功能 假如控制器C想利用代理给控制器A传值,那么 控制器C要有一个协议 控制器要有一个代理属性 控制器A遵守C的代理协议,并且成为C的代理对象. 控制器C的.h文件中作出如下声明:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 
 | //// DelegateVC.h
 // 反向传值
 //
 // Created by 两好三坏 on 16/3/5.
 // Copyright © 2016年 qinakun. All rights reserved.
 //
 import UIKit/UIKit.h
 @class DelegateVC;
 //协议
 @protocol DelegateVCDelegate
 //A需要实现的代理方法
 -(void)changeValue:(NSString *)string;
 @end
 @interface DelegateVC : UIViewController
 //代理属性
 @property(nonatomic,weak) iddelegate;
 @end
 [/objc]
 然后在.m文件中代码:
 [objc]
 //
 // DelegateVC.m
 // 反向传值
 //
 // Created by 两好三坏 on 16/3/5.
 // Copyright © 2016年 qinakun. All rights reserved.
 //
 import "DelegateVC.h"
 define kWidth [UIScreen mainScreen].bounds.size.width
 define kHeight [UIScreen mainScreen].bounds.size.height
 @interface DelegateVC ()
 @property(nonatomic,strong) UITextField *textValue;
 @end
 @implementation DelegateVC
 - (void)viewDidLoad {
 [super viewDidLoad];
 self.view.backgroundColor = [UIColor whiteColor];
 创建一个输入框,添加到控制器C的view上;
 UITextField _tf = [[UITextField alloc] init];
 tf.backgroundColor = [UIColor grayColor];
 tf.frame = CGRectMake(kWidth _0.5 - 50, kHeight * 0.5, 100, 40);
 self.textValue = tf;
 [self.view addSubview:_textValue];
 }
 //当控制器C消失的时候调用的方法
 -(void)viewWillDisappear:(BOOL)animated{
 [super viewWillDisappear:animated];
 //如果有对象响应了代理,就执行if判断中的方法,
 if ([self.delegate respondsToSelector:@selector(changeValue:)]) {
 //把输入框中的text取出来作为代理方法的参数传送给控制器A
 [self.delegate changeValue:self.textValue.text];
 }
 }
 @end
 
 | 
在页面中传值得方法有很多,使用通知,KVO,单例,还有偏好设置,归档解档都可以实现,看情况哪个方便就是用哪个咯….