系统分配了16个字节给NSObject对象(通过malloc_size函数获得),但NSObject对象内部只使用了8个字节的空间(64bit环境下,可以通过class_getInstanceSize函数获得)。
instance对象的isa指向class对象; %20class对象的isa指向meta-class对象; %20meta-class对象的isa指向基类的meta-class对象;
isa指向
对象方法、属性、成员变量、协议信息,存放在class对象中; 类方法,存放在meta-class对象中; 成员变量的具体值,存放在instance对象;
执行addOberser时 利用RuntimeAPI动态生成一个子类,并且让instance对象的isa指向这个全新的子类,当修改instance对象的属性时,会调用Foundation的_NSSetXXXValueAndNotify函数: -> willChangeValueForKey: -> 调用父类原来的setter -> didChangeValueForKey: -> 内部会触发监听器(Oberser)的监听方法( observeValueForKeyPath:ofObject:change:context:)
KVC的全称是Key-Value Coding,俗称“键值编码”,可以通过一个key来访问某个属性。
常见的API - (void)setValue:(id)value forKeyPath:(NSString *)keyPath; - (void)setValue:(id)value forKey:(NSString *)key; - (id)valueForKeyPath:(NSString *)keyPath; - (id)valueForKey:(NSString *)key;
setValue:forKey:的原理
valueForKey:的原理
Category的底层结构
Category的加载处理过程
如何实现给分类“添加成员变量”?
关联对象的原理
+load方法
+initialize方法
block本质上是封装了函数调用以及函数调用环境的OC对象,它内部也有个isa指针。
block的变量捕获(capture)
block的类型
各个类型的Block使用场景
__block修饰符
被__block修饰的对象类型
weak 关键字的作用弱引用,所引用对象的计数器不会加一,并在引用对象被释放的时候自动被设置为 nil。
weak是Runtime维护了一个hash(哈希)表,用于存储指向某个对象的所有weak指针。weak表其实是一个hash(哈希)表,Key是所指对象的地址,Value是weak指针的地址(这个地址的值是所指对象指针的地址)数组。
1、调用objc_release 2、因为对象的引用计数为0,所以执行dealloc 3、在dealloc中,调用了_objc_rootDealloc函数 4、在_objc_rootDealloc中,调用了object_dispose函数 5、调用objc_destructInstance 6、最后调用objc_clear_deallocating: 1、从weak表中获取废弃对象的地址为键值的记录 2、将包含在记录中的所有附有 weak修饰符变量的地址,赋值为nil 3、将weak表中该记录删除 4、从引用计数表中删除废弃对象的地址为键值的记录