Objective-C 语言特性
分类
分类可以做什么
- 声明私有方法
- 分解体积庞大的类文件
- 把framework的私有方法公开
分类的特点
- 运行时决议
- 可以为系统类添加分类
分类可以添加那些内容
- 实例方法
- 类方法
- 协议
- 属性:不是实例变量
分类总结 源码可知悉
分类方法会覆盖原类方法
同名分类方法谁能生效取决于编译顺序
名字相同的分类会引起编译报错
关联对象
怎么给分类添加成员变量
通过关联对象的技术,associate
id objc_getAssociated
void objc_setAssociated
void objc_removeAssociated
关联对象,关联到哪里去了呢
关联对象有AssociationsManager管理并在AssociationsHashMap存储
所有对象的关联内容都在同一个全局容器中
扩展
一般用扩展做什么?
- 声明私有属性
- 声明私有方法
- 声明私有成员变量
扩展的特点
- 编译时决议
- 只以声明的形式存在,多数在宿主中类的.m
- 不能为系统类添加扩展
分类和扩展的区别
从特点出发
代理
- 准确来说是一种软件设计模式
- iOS中以@protocol形式体现
- 传递方式一对一
一般声明为weak以规避循环引用
通知
- 是使用观察者模式来实现的用于跨层传递消息的机制
- 传递方式是一对多
KVO
-
KVO是key-value Observing的缩写
-
KVO是Objective C对观察者设计模式的又一实现
-
Apple使用了isa混写(isa-swizzling)来实现KVO
KVO面试题
-
通过KVC设置value能否生效 --- 能生效
-
通过成员变量赋值value能否生效 (_value = xx)--- 不能生效
- 除非加上willchange和didchange方法
-
使用setter方法改变值才能使KVO生效
KVC
KVC是key-value coding的缩写,主要是以下两个方法
- valueForKey
- setValueForKey
valueForKey 流程
setValueForKey 流程
属性关键字
-
读写权限
- readOnly
- readWrite(默认)
-
原子性
- atomic(默认)赋值和获取是安全,但是操作(添加、删除)是不一定能保证线程安全的
- nonatomic
-
引用计数
-
retain/strong
-
copy
-
assign
- 基本数据类型 ,int、bool
- 修饰对象类型,不改变其引用计数
- 移除时,会产生悬垂指针,仍然指向元类对象
-
weak 弱引用
- 不改变被修饰对象的引用计数
- 所指对象在被释放之后会自动置为nil
-
Copy
浅拷贝
浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间
- 会增加对象的引用计数
- 不会发生新的内存分配
深拷贝
- 会产生新的内存分配
- 不会增加原对象的引用计数
- 可变对象的copy和mutableCopy都是深拷贝
- 不可变对象的copy是浅拷贝,mutableCopy是深拷贝
- copy返回的对象都是不可变对象
@property(copy)NSMutableArray *array?会有什么问题
- 如果赋值过来是NSMutableArray,copy之后是NSArray
- 如果赋值过来是NSArray,copy之后还是NSArray
面试总结
-
简述分类实现原理
- 由运行时实现
- 最后添加的同名方法会覆盖
-
KVO的实现原理
- 观察者模式的实现
- isa 混写,运行时新增了该类的子类,然后重写setter方法,然后重新指向isa
-
能否为分类添加成员变量?为什么不可以?如果要,要怎么实现?
- 不可以添加成员变量
- category 它是在运行期决议的。 因为在运行期即编译完成后,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的。分类里面不能添加Ivar是因为分类本身并不是一个真正的类,它并没有自己的ISA。类最开始生成了很多基本属性,比如IvarList,MethodList,分类只会将自己的method attach到主类,并不会影响到主类的IvarList。这就是为什么分类里面不能增加成员变量的原因。
- 关联对象方法可以