1、retain和strong
他俩都是强引用,除了某些情况下不一样,其他的时候也是可以通用的。
在修饰block属性的时候,相信大家都知道要用copy吧,因为如果不copy的话,block是存放在栈连里面的,他的生命周期会随着函数的结束而出栈的,copy之后会放在堆里面。
strong在修饰block的时候就相当于copy,而retain修饰block的时候就相当于assign,这样block会出现提前被释放掉的危险。
2、能否向编译后得到的类中增加实例变量?能否向运行时创建的类中添加实例变量?为什么?
不能向编译后得到的类中增加实例变量;
能向运行时创建的类中添加实例变量;
因为编译后的类已经注册在 runtime 中,类结构体中的objc_ivar_list实例变量的链表 和instance_size实例变量的内存大小已经确定,同时runtime 会调用class_setIvarLayout或class_setWeakIvarLayout来处理 strong weak 引用。所以不能向存在的类中添加实例变量;
运行时创建的类是可以添加实例变量,调用class_addIvar函数。但是得在调用objc_allocateClassPair(创建类)之后,objc_registerClassPair(注册类)之前,原因同上。
当你观察一个对象时,一个新的类会被动态创建。这个类继承自该对象的原本的类,并重写了被观察属性的 setter 方法。重写的 setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象:值的更改。最后通过isa 混写(isa-swizzling)把这个对象的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么 ) 指向这个新创建的子类,对象就神奇的变成了新创建的子类的实例
键值观察通知依赖于 NSObject 的两个方法:willChangeValueForKey:和didChangevlueForKey:。在一个被观察属性发生改变之前,willChangeValueForKey:一定会被调用,这就会记录旧的值。而当改变发生后,observeValueForKey:ofObject:change:context:会被调用,继而didChangeValueForKey:也会被调用
4、load方法与initialize方法区别
load方法在这个文件被程序装载时调用,load方法总是在main函数之前调用。如果一个类没有实现load方法,那么就不会调用它父类的load方法。
5、runtime 中,SEL 和 IMP 的区别
SEL : 类成员方法的指针,但不同于C语言中的函数指针,函数指针直接保存了方法的地址,但SEL只是方法编号。
IMP:一个函数指针,保存了方法的地址