协议传值和属性传值
Block传值
Block传值与协议传值都适用于从后一个页面向前一个页面传值(反向传值)。
关于Block块
- 代码块本质上是和其他变量类似。不同的是,代码块存储的数据是一个函数体。使用代码块是,你可以像调用其他标准函数一样,传入参数数,并得到返回值。
使用Block进行传值
将B页面中Alabel.text
传回A页面中Blabel.text
,注意按照需求设置形参
第一步
- 在B页面的
BViewController.m
中定义声明Block属性
@interface NextViewController : UIViewController
@property (nonatomic, copy) void (^sendBlock) (NSString* Btext);
@property (nonatomic, strong) UILabel* firstLabel;
@end
第二步
- 在B跳转回A的按钮的点击事件中,使用第一步定义的sendBlock,把需要传递的值放进
^sendBlock()
中
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor greenColor];
_firstLabel = [[UILabel alloc] init];
_firstLabel.backgroundColor = [UIColor grayColor];
_firstLabel.frame = CGRectMake(200, 130, 90, 40);
_firstLabel.text = @"传一个值";
[self.view addSubview:_firstLabel];
UIButton* secondButton = [UIButton buttonWithType: UIButtonTypeSystem];
[secondButton setTitle:@"跳转回A页面" forState:UIControlStateNormal];
secondButton.frame = CGRectMake(180, 500, 120, 30);
secondButton.backgroundColor = [UIColor redColor];
[secondButton addTarget:self action:@selector(pressSecondButton) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:secondButton];
}
- (void)pressSecondButton {
_sendBlock (_firstLabel.text);
[self dismissViewControllerAnimated:NO completion:nil];
}
第三步
- 在A页面跳转到B页面按钮的事件函数中调用B页面设置的属性
sendBlock
- (void)viewDidLoad {
[super viewDidLoad];
_mainLabel = [[UILabel alloc] init];
_mainLabel.backgroundColor = [UIColor grayColor];
_mainLabel.frame = CGRectMake(100, 130, 140, 40);
_mainLabel.text = @"等待传值";
[self.view addSubview:_mainLabel];
self.view.backgroundColor = [UIColor whiteColor];
UIButton* firstButton = [UIButton buttonWithType:UIButtonTypeSystem];
firstButton.backgroundColor = [UIColor orangeColor];
[firstButton addTarget:self action:@selector(pressFirstButton) forControlEvents:UIControlEventTouchUpInside];
[firstButton setTitle:@"跳转到B页面" forState:UIControlStateNormal];
firstButton.frame = CGRectMake(180, 500, 120, 30);
[self.view addSubview:firstButton];
}
- (void)pressFirstButton {
NextViewController* nextViewController = [[NextViewController alloc] init];
nextViewController.block = ^(NSString* Btext) {
self->_mainLabel.text = Btext;
};
nextViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:nextViewController animated:NO completion:nil];
}
KVO传值
概述
- KVO全称
KeyValueObserve
也就是观察者模式,是apple提供的一套事件通知机制.允许对象监听另一个对应特殊属性的改变,并在改变时接受到该事件.一般继承自NSObject
的对象都默认是支持KVO.
使用KVO传值
第一步
- 注册观察者
在A页面跳转B页面的事件函数中,注册观察者
关于该方法的各个参数:
@observer:
观察者,也就是被观察者对象发生改变时通知的接收者
@keyPath:
被观察者的属性名
@options:
参数,options一般选择NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
,这样当属性值发生改变时我们可以同时获得旧值和新值,如果我们只填NSKeyValueObservingOptionNew
则属性发生改变时只会获得新值
@context:
这个参数可传入任意类型的对象,这个值会传递到接受消息回调的代码中,是kVO的一种传值方式.
[self.second addObserver:self forKeyPath:@"userName" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
第二步
- 设置当所观察的属性发生改变时调用的函数
关于该函数的各个参数:
@keyPath:
被观察者的属性名
@object:
观察对象
@change:
这是一个字典类型的值,通过键值对显示新的属性值和旧的属性值
@context:
上面添加观察者时传递的信息
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
//此处监听key对应值的变化情况
if ([keyPath isEqualToString:@"userName"]) {
_mainLabel.text = _second.userName;
}
}
第三步
-
移除观察者,设置该函数
-
使用取消注册方法
- (void)dealloc {
[_second removeObserver:self forKeyPath:@"userName"];
}
通知传值
概述
(NSNotification)通知中心传值,可以跨越多个页面传值, 一般也是从后面的页面传给前面的页面。
通知传值的使用
第一步
- 在注册A页面注册通知
第三个参数的事件名:系统用这个参数来区别不同事件。
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tongzhi:)name:@"tongzhi" object:nil];
第二步
- 在A页面的.m文件设置接收到通知的事件
- (void)tongzhi:(NSNotification *)text {
NSLog(@"%@",text.userInfo[@"textOne"]);
_mainLabel.text = text.userInfo[@"textOne"];
NSLog(@"-----接收到通知------");
}
第三步
- 在第一个界面中的dealloc中, 将通知中心remove掉
- 移除通知:
removeObserver:
和removeObserver:name:object:
- 其中,
removeObserver:
是删除通知中心保存的调度表一个观察者的所有入口,而removeObserver:name:object:
是删除匹配了通知中心保存的调度表中观察者的一个入口。 - 注意参数
removeObserver
为要删除的观察者,一定不能置为nil。
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"tongzhi" object:self];
}
第四步
- 在B界面中, 建立一个通知中心, 通过通知中心, 发送通知(发送通知的过程就是传值的过程,将要传输的值作为
object
的值传给A界面 - 发送通知,其中的
name
填写第一界面的name
, 系统知道是第一界面来相应通知,object
就是要传的值。userInfo
是一个字典, 如果要用的话,提前定义一个字典, 可以通过这个来实现多个参数的传值使用。
//添加 字典,将label的值通过key值设置传递
NSDictionary *dict =[[NSDictionary alloc]initWithObjectsAndKeys:self.firstTextField.text,@"textOne", nil];
//创建通知
NSNotification *notification =[NSNotification notificationWithName:@"tongzhi" object:nil userInfo:dict];
//通过通知中心发送通知
[[NSNotificationCenter defaultCenter] postNotification:notification];
效果图: