文章目录
KVO简介
KVO(Key-Value-Observing,键值观察),即观察关键字的值的变化。首先在子页面中声明一个待观察的属性,在返回主页面之前修改该属性的值。在主页面中提前分配并初始化子页面,并且注册对子页面中对应属性的观察者。在从子页面返回上主之前,通过修改观察者属性的值,在主页面中就能自动检测到这个改变,从而读取子页面的数据。KVO只对属性发生作用。
KVO传值适用的场景
已经通过push的方式进入到子页面,在从子页面返回主页面的时候(子页面会释放掉内存),需要在主页面中使用子页面中的数据,这是就可以利用代理反向传值。
传递方向
从后向前的传值
使用步骤
1.步骤一:在界面一注册观察者
使用的方法:addObserver:forKeyPath:options:context:
参数含义:P1:观察者,该对象必须实现 该对象必须实现 observeValueForKeyPath:ofObject:change:context: 方法。
P2:要观察的属性。
P3:选择监听返回的值的类型。
enum {
NSKeyValueObservingOptionNew 接收方法中使用change参数传入变化后的新值
NSKeyValueObservingOptionOld 接收方法中使用change参数传入变化前的旧值
NSKeyValueObservingOptionInitial change参数内容会包含新值
NSKeyValueObservingOptionPrior 如果加入这个参数,接收方法会在变化前后分别调用一次,共两次,变化前的通知change参数
};
P4:传入任意类型的对象,在"接收消息回调"的代码中可以接收到这个对象,是KVO中的一种传值方式。(注意:现在目前好像只可以使用nil,具体怎么用希望路过的大佬可以帮我回答一下)
接受通知:
使用方法:observeValueForKeyPath:ofObject:change:context:
删除KVO:
使用方法:removeObserver:forKeyPath:context
代码:
//FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
@interface FirstViewController ()
@property (strong, nonatomic) UITextField *textField;
@property (strong, nonatomic) UIButton *button;
//在主页面注册观察者,实现KVO的回调方法,并在主页面销毁时移除观察者
@property (strong, nonatomic) SecondViewController *subVC;
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"主界面";
_textField = [[UITextField alloc] init];
_textField.textColor = [UIColor whiteColor];
_textField.textAlignment = NSTextAlignmentCenter;
_textField.backgroundColor = [UIColor blackColor];
_textField.frame = CGRectMake(100, 100, 200, 60);
[self.view addSubview:_textField];
_button = [UIButton buttonWithType:UIButtonTypeCustom];
[_button setTitle:@"跳转到子界面" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[_button addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
_button.frame = CGRectMake(100, 300, 200, 60);
[self.view addSubview:_button];
}
- (void) btnClicked:(UIButton *)btn {
if (!_subVC) {
_subVC = [[SecondViewController alloc] init];
//注册观察者
[_subVC addObserver:self forKeyPath:@"content" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
}
[self.navigationController pushViewController:_subVC animated:YES];
// SecondViewController* second = [[SecondViewController alloc] init];
// [self.navigationController pushViewController:second animated:YES];
}
// KVO的回调,当观察者中的数据有变化时会回调该方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"content"]){
self.textField.text = self.subVC.content;
NSLog(@"old text:%@ new text:%@", [change objectForKey:NSKeyValueChangeOldKey], [change objectForKey:NSKeyValueChangeNewKey]);
//也可以这么写
// NSLog(@"old text:%@ new text:%@", [change objectForKey:@"old"], [change objectForKey:@"new"]);
}
}
- (void)dealloc {
//移除观察者
[self.subVC removeObserver:self forKeyPath:@"content"];
}
@end
//SecondViewController.m
#import "SecondViewController.h"
@interface SecondViewController ()
@property (strong, nonatomic) UITextField *textField;
@property (strong, nonatomic) UIButton *button;
@property (strong, nonatomic) NSString* content;
@end
@implementation SecondViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"子界面";
_textField = [[UITextField alloc] init];
_textField.textColor = [UIColor whiteColor];
_textField.textAlignment = NSTextAlignmentCenter;
_textField.backgroundColor = [UIColor blackColor];
_textField.frame = CGRectMake(100, 100, 200, 60);
[self.view addSubview:_textField];
_button = [UIButton buttonWithType:UIButtonTypeCustom];
[_button setTitle:@"跳转到主界面" forState:UIControlStateNormal];
[_button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[_button addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
_button.frame = CGRectMake(100, 300, 200, 60);
[self.view addSubview:_button];
}
//子页面在返回主页面时修改对应属性的内容,则会回调主页面的回调方法
- (void) btnClicked:(UIButton *)btn {
self.content = _textField.text;//修改属性的内容
[self.navigationController popViewControllerAnimated:YES];
}
@end
效果图:
参考文章:1.iOS KVO用法(附修改账号密码demo)
2.iOS学习——页面的传值方式iOS----KVC和KVO 详解