- Key Value Observing(鍵-值-觀察)
- 被觀察者和觀察者同時(shí)實(shí)現(xiàn)一個(gè)協(xié)議: NSKeyValueObserving
- 源于設(shè)計(jì)模式中的觀察者模式春畔。
- 指定被觀察對(duì)象的屬性被修改后,KVO就會(huì)自動(dòng)通知相應(yīng)的觀察者。
注意:不要忘記解除注冊(cè)铆农,否則會(huì)導(dǎo)致資源泄露
#pragma mark //////////KVO方法//////////
//注冊(cè)監(jiān)聽
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
//移除監(jiān)聽
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
//監(jiān)聽回調(diào)
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context;
使用KVO
Student.h文件
#import <Foundation/Foundation.h>
@interface Student : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end
KVOViewController.m文件中
1.監(jiān)聽Student的屬性
observer: 觀察者對(duì)象
keyPath: 被觀察的屬性
options: 設(shè)定通知觀察者時(shí)傳遞的屬性值
context: 一些其他的需要傳遞給觀察者的上下文信息
#import "KVOViewController.h"
#import "Student.h"
@interface KVOViewController ()
@end
@implementation KVOViewController{
Student *_student;
}
- (void)viewDidLoad {
[super viewDidLoad];
_student = [[Student alloc] init];
_student.name = @"LuisX";
_student.age = 24;
//為屬性添加觀察者
[_student addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(100, 100, 100, 100);
button.backgroundColor = [UIColor orangeColor];
[self.view addSubview:button];
[button addTarget:self action:@selector(changeStudentAgeValue:) forControlEvents:UIControlEventTouchUpInside];
}
@end
2.點(diǎn)擊button修改student的屬性
- (void)changeStudentAgeValue:(UIButton *)button{
_student.age++;
}
3.實(shí)現(xiàn)監(jiān)聽回調(diào)方法
keyPath: 被觀察的屬性
object: 被觀察者的對(duì)象
change: 屬性值,根據(jù)上面提到的Options設(shè)置,給出對(duì)應(yīng)的屬性值
context: 上面?zhèn)鬟f的context對(duì)象
//觀察者通過實(shí)現(xiàn)下面的方法膘壶,完成對(duì)屬性改變的響應(yīng)
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
if ([keyPath isEqualToString:@"age"] && object == _student) {
NSLog(@"age:%ld", _student.age);
NSLog(@"old age:%@", [change objectForKey:@"old"]);
NSLog(@"new age:%@", [change objectForKey:@"new"]);
//輸出: age:25
//輸出: old age:24
//輸出: new age:25
}
}
4.移除監(jiān)聽
- (void)viewDidDisappear:(BOOL)animated{
[super viewDidDisappear:animated];
//移除觀察者
[_student removeObserver:self forKeyPath:@"age"];
}