内容要点
分类
扩展
关联对象
代理
通知
KVC
属性关键字
分类
分类可以做什么?
1 实例方法
2 类方法
3 协议
4 属性
作用是:声明私有方法,分解庞大的类文件
分类的结构如下:
struct category_t {
const char *name;
classref_t cls;
struct method_list_t *instanceMethods;
struct method_list_t *classMethods;
struct protocol_list_t *protocols;
struct property_list_t *instanceProperties;
……
}
分类特点
1 运行时决议:编译时没有添加,运行时才通过Runtime添加
2 最后编译的类,最先添加到数组中。方法查找时,根据选择器名称查找,最优先查找头部方法。
第一步:依次编译分类A、B、C
第二步:运行时,有个二维数组,倒序添加编译过的分类(CBA)
第三步:在宿主方法列表的index=0的位置,插入二维数组中的内容
结论
分类添加的方法可以“覆盖”原类方法。
同名分类方法谁能生效取决于编译顺序,最后编译的,最优生效。
名字相同的分类会引起编译报错
扩展Extension
扩展可以做什么?
1 声明私有属性
2 声明私有方法(仅方便阅读)
3 声明私有成员变量
扩展和分类区别
1 分类是运行时决议,扩展是编译时决议
2 分类可以有声明有实现,扩展只有声明,实现写在宿主的.m中
3 可以给系统类添加分类,不能给系统类添加扩展
运行时决议:编译期并没有把分类方法添加到宿主类中,而是在运行时才添加。
关联对象
关键方法
能否为分类添加成员变量? 可以,使用关联对象
id objc_getAssociatedObject(id object, const void *key)
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
void objc_removeAssociatedObjects(id object)
关联对象的本质
所有关联对象内容都在同一个全局容器中。使用AssociationsManager 管理并在AssociationsHashMap存储。
代理Delegate
代理是一种软件设计模式,iOS中以@protocol形式实现,传递方式一对一
通知Notification
使用观察者模式来实现跨层传递消息的机制,传递方式一对多
KVO
1 KVO是 观察设计者模式的实现
2 Apple使用了isa 混写(isa - swizzling)来实现KVO
生效条件
1 使用setter方法改变值KVO才会生效
2 使用setValue: forKey: 改变值KVO会生效
3 成员变量直接修改需手动添加KVO才会生效(willChangeValueForKey didChangeValueForKey)
isa混写就是指改变isa的指向。假设Person对象person添加了KVO观察后,会在运行时生成一个Person的子类NSKVONotifying_Person, 那么person的isa是指向Person类的,此时会被重写,改为指NSKVONotifying_Person类。NSKVONotifying_Person类修改了setter方法。
KVC
键值编码技术 在 NSObject(NSKeyValueCoding)中定义
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKey:(NSString *)key;
无论调用setValue还是valueForKey,key必须是类定义的。否则会抛异常.
由于可以通过这种方式改变私有变量,所以会破坏面向对象编程思想。
setValue调用顺序
setter方法,变量,如果还是没有setValue:forUndefinedKey:抛异常
valueForKey调用顺序
getter方法,变量,valueForUndefinedKey抛异常
属性关键字
读写权限
readonly readwrite. default is readwrite
原子性
atomic(赋值,获取线程安全) nonatomic . default is atomic.
atomic修饰的数组,数组赋值与获取保证线程安全。但是数组添加,移除不负责线程安全。
引用计数
retain/strong
assign/unsafe_unretained (基本,对象)/MRC
weak
copy
assign和weak区别 ?
assign 会产生悬垂指针
不改变被修饰对象的引用计数
修饰基本数据类型,如int BOOL等
weak
不改变被修饰对象的引用计数
所修饰的对象被释放之后会自动置为nil
copy关键字
copy后的都是不可变的
mutableCopy的都是可变的
只有不可变对象的 copy是浅拷贝,其他都是深拷贝
总结
@property(copy)NSMutableArray *array?
可能会造成程序崩溃
原因是:array不管是NSMutableArray还是NSArray经过copy后,都是NSArray。
NSMutableArray经过copy是深拷贝,产了NSArray不可变对象
NSArray经过copy是浅拷贝,产生了NSArray指针。
但是由于array被声明为NSMutableArray所以,可能会调用addObject这些方法,导致崩溃。
MRC重写retain修饰变量的setter方法?
if(_obj != obj){
[_obj release];
_obj = [obj retain];
}
分类实现原理?
运行时决议,不同分类同名方法,最后参与编译的最终生效。
KVO实现原理?
观察着模式实现,运用了isa混写技术,动态添加子类。让isa指向子类。
网友评论