1.KVO分为自动和手动
当+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key为YES的时候自动观察,可以观察到属性的变化
当为NO的话在set方法前后willChangeValueForKey didChangeValueForKey既可以观察到属性的变化
2.当观察数组的元素变化的时候,不可以直接观察,可以使用kvc进行观察
NSMutableArray *arr = [self.personPeople mutableArrayValueForKey:@"arr"];
[arraddObject:@"123"];
3.当观察一个类对象的时候,可以分别观察类对象.属性:
[paddObserver:self forKeyPath:@"dogg.age" options:(NSKeyValueObservingOptionNew) context:nil];
也可以使用这个方法来
+(NSSet *)keyPathsForValuesAffectingValueForKey:(NSString*)key
{
NSLog(@"%@",key);
NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];
if([keyisEqualToString:@"dogg"]) {
NSArray *arr = @[@"_dogg.age",@"_dogg.ageee"];
keyPaths = [keyPathssetByAddingObjectsFromArray:arr];
}
returnkeyPaths;
}
此时观察的时候:
[paddObserver:self forKeyPath:@"dogg" options:(NSKeyValueObservingOptionNew) context:nil];即可观察到dogg的age和ageee的属性变化
4.根据KVO的原理,动态创建被观察类的子类,并添加set方法(其实创建子类并不意味着我们就有了该属性的set方法,否者也不会出现通过继承关系找类的实现),在改变前后告诉被观察者属性的改变,并通过isa指针指向元类
此时我们可以自己写kvc的观察
- (void)MT_addObserver:(NSObject*)observer forKeyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options context:(void*)context{
//1.判断kayPath是否存在
SELsetterSeletor =NSSelectorFromString([NSStringstringWithFormat:@"set%@:",keyPath.capitalizedString]);
ClasssuperClass =object_getClass(self.class);
//2.自定义一个被观察类的子类
NSString*oldClassName =NSStringFromClass(self.class);
NSString*newClassName = [NSStringstringWithFormat:@"MTKVO_%@",oldClassName];
//创建一个类
ClassnewClass =objc_allocateClassPair(self.class, newClassName.UTF8String,0);
//注册该类
objc_registerClassPair(newClass);
//2.动态修改该类和被观察类绑定
object_setClass(self, newClass);
//3.添加setName方法,此时一定要对应setName这样类似的方法,IMP是函数指针找到对应的函数,“V”表示void,@表示oc参数
class_addMethod(newClass, setterSeletor, (IMP)haha,"v@:@");
}
//oc方法中有2个隐藏参数:id self,SEL _cmd,此时应该添加上,否者打印不出对应属性
voidhaha(idself,SEL_cmd,NSString*newName){
NSLog(@"%@",newName);
}
网友评论