拓展 VS 分类
一般用扩展做什么?
- 声明私有属性
- 声明私有方法
- 声明私有成员变量
扩展的特点 (和分类的区别)
- 编译时决议
- 只以声明的形式存在,多数情况下寄生于宿主类的.m中
- 不能为系统类添加扩展
KVO 和 KVC
KVO
KVO实现:使用 isa-swizzling 来实现KVO
当调用了 addObserver:forkeypath 方法之后,系统会动态创建 NSKVONorifying_A 类,同时将A的isa指针指向 NSKVONorifying_A
子类拥有自己的set方法实现,内部会调用
1 | -willChangeValueForKey: |
KVC
主要有这俩个方法
通过一副流程图看一下 valueForKey 的实现逻辑
1 | -(id)valueForKey:(NSString *)key |
首先系统会判断访问的key是否有对应的getter方法,存在就直接进行调用,不存在就判断实例变量是否存在,通过 accessInstanceVariablesDirectly 来判断 ,默认是YES。 如果不存在,会调用 UndefinedKey ,抛出异常.
KVC VS KVO
KVC,即是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。
一个对象拥有某些属性。比如说,一个 Person 对象有一个 name 和一个 address 属性。以 KVC 说法,Person 对象分别有一个 value 对应他的 name 和 address 的 key。 key 只是一个字符串,它对应的值可以是任意类型的对象。从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另一个是获取 key 的值
Copy 属性关键字
浅拷贝和深拷贝的概念
Copy 修饰对象
总结下来三点
- 可变对象的 copy 和mutableCopy都是深拷贝
- 不可变对象的copy是浅拷贝,mutableCopy是深拷贝
copy方法返回的都是不可变对象
成员变量捕获
1 | - (void)catchIvar |
上面两份代码是等价的,系统为什么要转化成self->_ivarA的形式去捕获self呢?而不是直接捕获_ivarA
正常的方法中,直接使用成员变量ivar,编译器都会自动转化为self->ivar,之所以这样做,是因为正常的消息发送中,self是会作为一个参数,传递到objc_send方法中的。所以在任何方法中都可以直接获取到self,而成员变量ivar,并没有作为任何参数传入到方法中,所以为了访问到ivar,正常都会转化为self->ivar来访问。