在iOS开发新中经常会遇到在两个界面之间进行传值的情况,在页面之间进行数据传递有正向传递(控制器A跳转到控制器B),也有反向传值(控制器B跳转到A).可以通过属性,代理,block,通知等等. 就解释一下怎么使用block和代理进行页面之间反向传值;

使用block进行反向传值 在Xcode中创建新的项目 创建两个控制器A,B. 在A控制器中添加一个按钮,对按钮添加点击跳转到B控制器,然后再A中再次添加一个label,作为接受B控制器中传回来的值. 在B控制器中创建一个UITextField,用于输入信息. 在A控制器中.m文件中代码如下:

1
2
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文件中声明如下:

1
2
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文件中作出如下声明:

1
2
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,单例,还有偏好设置,归档解档都可以实现,看情况哪个方便就是用哪个咯….