iOS底层学习-day-4
前言-OC语法篇
我是一名iOS开发者, iOS底层 菜鸟的进阶之路30天。
问题
iOS用什么方式实现对一个对象的KVO?(KVO的本质是什么?)
- 利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类
- 当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数
- willChangeValueForKey:
- 父类原来的setter
- didChangeValueForKey:
- 内部会触发监听器(Oberser)的监听方法(observeValueForKeyPath:ofObject:change:context:)
如何手动触发KVO? 问题没意义
- 手动调用willChangeValueForKey:和didChangeValueForKey:
直接修改成员变量会触发KVO么?
- 不会触发KVO
KVO本质(KVO的效率比代理的效率低)
使用了KVO与没有使用KVO对象的区别
- KVO动态生成的子类和person的方法实现地址的区别
// NSKVONotifying_MJPerson是使用Runtime动态创建的一个类,是MJPerson的子类,而且NSKVONotifying_MJPerson子类superclass指向父类MJPerson
// self.person1.isa => NSKVONotifying_MJPerson
[self.person1 setAge:21];//使用了KVO监听
// self.person2.isa => MJPerson
[self.person2 setAge:22];
- 窥探person的KVO的方法
NSKVONotifying_MJPerson中的 setAge方法
- (void)setAge:(int)age {
_NSSetIntValueAndNotify();
}
// 伪代码
void _NSSetIntValueAndNotify() {
[self willChangeValueForKey:@"age"];
[super setAge:age];
[self didChangeValueForKey:@"age"];
}
- (void)didChangeValueForKey:(NSString *)key {
// 通知监听器,某某属性值发生了改变
[oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
}
打印出setAge方法@implementation具体实现在哪里
[self.person1 methodForSelector:@selector(setAge:)];
p (IMP)0x1065687c0//lldb中直接输入类_person1的(IMP)
KVO的内部实现-NSKVONotifying_MJPerson
- KVO内部方法实现
- (Class)class {
return [MJPerson class];
}
- (void)dealloc {
// 收尾工作
}
- (BOOL)_isKVOA {
return YES;
}
方法的遍历
- (void)printMethodNamesOfClass:(Class)cls {
unsigned int count;
// 获得方法数组
Method *methodList = class_copyMethodList(cls, &count);
// 存储方法名
NSMutableString *methodNames = [NSMutableString string];
// 遍历所有的方法
for (int i = 0; i < count; i++) {
// 获得方法
Method method = methodList[i];
// 获得方法名
NSString *methodName = NSStringFromSelector(method_getName(method));
// 拼接方法名
[methodNames appendString:methodName];
[methodNames appendString:@", "];
}
// 释放
free(methodList);
// 打印方法名
NSLog(@"%@ %@", cls, methodNames);
}