iOS使用KVO設(shè)置鍵值觀察依賴鍵
應(yīng)用場(chǎng)景:一個(gè)對(duì)象的屬性之間是相互關(guān)聯(lián)的,也就是對(duì)象的一個(gè)屬性依賴于另一個(gè)對(duì)象的一個(gè)獲多個(gè)屬性梢薪。如果這些被依賴屬性中的任意一個(gè)值發(fā)生改變,那么原屬性的值也會(huì)發(fā)生相應(yīng)的改變尝哆。
實(shí)戰(zhàn):首先定義類(lèi)Student秉撇,Person。Person作為Student的屬性定義。
Student中的infomation依賴于Person中的name和age琐馆。
@interface Person : NSObject
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) NSInteger age;
@end
@interface Student : NSObject
@property(nonatomic, copy) NSString *infomation;
@property(nonatomic, strong) Person *person;
@end
要實(shí)現(xiàn)上述依賴關(guān)系规阀,對(duì)象類(lèi)需要實(shí)現(xiàn)以下兩點(diǎn):
- 需要手動(dòng)實(shí)現(xiàn)infomation的setter和getter。
- 實(shí)現(xiàn)keyPathsForValuesAffectingValueForKey: 或 keyPathsForValuesAffectingInfomation方法瘦麸。這兩個(gè)方法的作用是告訴系統(tǒng)infomation屬性依賴于person中的age和name屬性谁撼。
@implementation Student
- (instancetype)init {
if (self = [super init]) {
self.infomation = @"";
self.person = [[Person alloc]init];
self.person.name = @"";
self.person.age = 0;
}
return self;
}
- (NSString *)infomation {
return [NSString stringWithFormat:@"student_name = %@ | student_age = %ld",self.person.name,self.person.age];
}
- (void)setInfomation:(NSString *)infomation {
NSArray *array = [infomation componentsSeparatedByString:@"#"];
if (array && array.count == 2) {
self.person.name = array[0];
self.person.age = ((NSNumber *)array[1]).integerValue;
}
}
+ (NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key {
if ([key isEqualToString:@"infomation"]) {
NSSet *set = [NSSet setWithObjects:@"person.name", @"person.age",nil];
return set;
}
return nil;
}
//+ (NSSet<NSString *> *)keyPathsForValuesAffectingInfomation {
// NSSet *set = [NSSet setWithObjects:@"person.name", @"person.age",nil];
// return set;
//}
@end
KVO實(shí)現(xiàn):
1.初始化student,并且為student添加觀察者滋饲,觀察information屬性(注意此處是觀察information)厉碟,以及實(shí)現(xiàn)observeValueForKeyPath:ofObject:change:context回調(diào)方法。
2.點(diǎn)擊觸發(fā)修改person中的name和age了赌。
- (void)viewDidLoad {
[super viewDidLoad];
self.student = [[Student alloc]init];
[self.student setInfomation:@"Charlie#30"];
[self.student addObserver:self forKeyPath:@"infomation" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"infomation"]) {
NSLog(@"OBSERVE : old infomation = %@ | new infomation = %@", change[NSKeyValueChangeOldKey], change[NSKeyValueChangeNewKey]);
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
self.student.person.name = @"Vivian";
self.student.person.age = 40;
}
輸出:
2019-01-11 10:32:42.533291+0800 CLTestKVO[37577:1834387] OBSERVE : old infomation = student_name = Charlie | student_age = 30 | new infomation = student_name = Vivian | student_age = 30
2019-01-11 10:32:42.533465+0800 CLTestKVO[37577:1834387] OBSERVE : old infomation = student_name = Vivian | student_age = 30 | new infomation = student_name = Vivian | student_age = 40
通過(guò)輸出結(jié)果可以看出墨榄,當(dāng)修改了name和age的時(shí)候玄糟,infomation屬性會(huì)收到觀察者的通知勿她。注意,此處收到了兩次通知阵翎,分別是修改name和修改age對(duì)應(yīng)的觀察者通知逢并。