Objective-C相关常见问题
2018-08-06 本文已影响1人
繁华落尽丶lee
一、分类
分类都做了什么?
- 声明私有方法
- 分解体积庞大的类文件
- 把Framework的私有方法公开化
分类的特点
- 运行时决议,编好分类后并没有直接添加到宿主类中,而是在运行时通过Runtime添加到宿主类中。
- 可以为系统类添加分类。
分类可以添加哪些内容
- 实例方法
- 类方法
- 协议
- 属性,只是添加了setter和getter方法。
Runtime中有源码。
多个分类中有同名方法,哪个方法会生效?
最后编译的分类中的方法会生效。倒序遍历,所以最先添加的那个生效。
分类中的方法会“覆盖”宿主类的方法的原因
因为分类中的方法会插入到宿主方法列表数组的前边,先查找到返回。
分类的机制或者原理
- 分类添加的方法可以“覆盖”原类方法
- 同名分类方法谁生效取决于编译顺序
- 名字相同的分类会引起编译报错
能否为分类添加实例变量
可以通过关联对象实现
消化这篇文章Category不再是问题 深入理解Objective-C:Category -- 美团技术团队
二、关联对象
什么是关联对象
id objc_getAssociatedObject(id object, const void * key) // 通过key在Object获取关联的
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
void objc_removeAssoicatedObjects(id object)
成员变量被添加到哪里了?
关联对象有AssociationsManager
管理并在AssociationHashMap
存储,
所有对象的关联内容都在同一个全局容器中。
AssociationsHashMap --> ObjectAssociationMap --> ObjectAssociation
![](https://img.haomeiwen.com/i1363078/b088ef03c857f6cb.png)
参考文章关联对象 AssociatedObject 完全解析
三、扩展
做什么?
- 声明私有属性
- 声明私有方法
- 声明私有成员变量
与分类的区别
- 编译时决议
- 只以声明的形式存在,多数情况下在宿主类的.m中
- 不能为系统类添加扩展
四、代理
什么代理
- 一种软件设计模式
- iOS当中以@protocol形式体现
- 传递方式一对一
工作流程
![](https://img.haomeiwen.com/i1363078/235897b3df09f7e4.png)
问题
- 一般声明为weak以规避循环引用。代理方strong委托方,委托方weak代理方。
五、通知
特点
- 使用
观察者模式
实现的用于跨层传递消息的机制 - 传递方式一对多
实现机制和原理是怎样的
发送者 ---> 通知中心 ---> 多个接收者
怎样实现通知机制?
Notification_Map ---> NotificationObject
六、KVO
什么是KVO?
- KVO是OC对观察者模式的一种实现
- Apple使用isa混写(isa-swizzling)来实现KVO。
实现机制
![](https://img.haomeiwen.com/i1363078/f92cae629850bf39.png)
系统在运行时,动态创建了一个子类NSKVONotifying_A类,重写Setter方法。
重写的Setter添加的方法
- (void)willChangeValueForKey:(NSString *)key;
- (void)didChangeValueForKey:(NSString *)key;
// NSKVONotifying_A 的Setter实现
- (void)setValue:(id)obj {
[self willChangeValueForKey: @"keyPath"];
// 调用父类实现,也即原类的实现
[super setValue:obj];
[self didChangeValueForKey: @"keyPath"];
}
KVC会触发KVO吗?
会,setValue:forKey:会调用,KVO重写的Setter方法。
通过成员变量直接赋值是否能触发KVO?
不会,需要调用willChangeValueForKey:
和didChangeValueForKey:
,这是手动KVO的实现。
总结
- 使用Setter方法改变值KVO能生效
- 使用setValue:forKey:改变值KVO能生效
- 成员变量直接修改需要手动添加KVO才会生效
七、KVC
什么是KVC?
KVC是Key Value coding的缩写,键值编码技术。
- (id)valueForKey:(NSString *)key
- (Void)setValue:(id)value forKey:(NSString *)key
八、属性关键字
属性关键字的分类
- 读写权限
- 原子性
- 引用计数
读写权限
- readonly
- readWrite(默认)
原子性
- atomic (默认)
- nonatomic
引用计数
- retain/strong
- assign/unsafe_unretained
- weak
- copy
assign和weak的区别
assign
- assign可以修改基本数据类型
- 修改对象类型,不改变引用计数
- 释放后,还会指向原地址,会产生悬垂指针
weak
- 不改变被修改对象的引用计数
- 所指对象在释放之后自动置为nil
copy
@propery (copy) NSMutableArray *array;
问题:
浅拷贝和深拷贝
- 浅拷贝,复制内存地址,增加引用计数,没有发生新的内存分配。
- 深拷贝,新开辟内存,复制内容。不会增加引用计数,开辟新的内存空间。
区别?
- 是否开辟新的内存空间?
- 是否影响引用计数?
copy关键字使用
- 可变对象 --> copy操作后 ==> 生成不可变对象 ==> 深拷贝
- 可变对象 --> mutableCopy ==> 可变 ==> 深拷贝
- 不可变对象 --> copy ==> 不可变 ==> 浅拷贝
- 不可变对象 --> mutableCopy ==> 可变 ==> 深拷贝
总结
- 对于可变对象的copy和mutableCopy都是深拷贝
- 不可变对象的Copy是浅拷贝,mutableCopy是深拷贝
- copy方法返回不可变对象