1. OC对象模型
- 1.1 什么是isa指针
每个对象都有一个isa指针,指向其对应的类。类的指针指向其元类(元类是因为在OOP思想中,类也是一个对象,也必须是另外一个类的实例,这个类就是元类),元类的isa指针指向其父类。根元类的isa指针指向自己,形成一个闭环。
- 1.2 类的成员变量
类的成员变量在内存中类似结构体的存储形式,不能动态改变其大小。而成员方法是被指针指向的,可以动态改变。这也是category只能为对象增加成员方法,而不能增加成员变量的原因。
既然成员方法可以动态改变,可通过下一节在运行时过程中动态改变成员方法的实现。
- 1.3 应用
动态改变成员方法需要用到系统提供的运行时API。头文件是objc/runtime.h。
比较有用的API列举如下:
objc_allocateClassPair | 创建新的类 |
objc_registerClassPair | 注册新的类 |
class_addMethod | 给类添加新的方法 |
object_getClass | 获得对象的isa指针所指向的对象 |
用来改变成员方法实现的API:(Method Swizzling)
class_replaceMethod | 需要替换的方法可能不存在时 |
method_exchangeImplementations | 需要交换两个方法的实现时 |
method_setImplementation | 为某个方法设置其实现方式时,这个最常用来替换系统的API。 |
应用场景例如:
- 1)替换系统的imageNamed对象方法,可根据规则设置某些设备中使用一套图片资源,在另一些类型设备使用另一套图片资源。
- 2)系统的UIImagePickerController在iPad横屏下有转屏的bug,为了解决该系统bug,可用method swizzling API 替换系统方法的实现。
2. Tagged Pointer对象
- 2.1 用于解决什么问题
解决iphone 5s出现x64系统后,数据类型所占大小也相应增大导致占用更大的内存产生的内存浪费问题。可节省内存和提高执行效率。
- 2.2 原理
把对象的指针拆成两部分,一部分用来存储数据,另一部分作为特殊标记,表示为一个特殊的指针,不指向任何一个地址。Tagged Pointer通过在最后一个bit位设置一个特殊标记,将数据直接保存在指针本身中。
- 2.3 使用时的注意点
tagged pointer并不是真正的对象,没有isa指针,所以不要直接访问其Isa变量。
3. Block对象模型
- 3.1 block有哪几种
有三种,静态全局block,栈block,堆block.
- 3.2 block的复制机制
block中访问到的外部局部变量是对该局部变量值的切片复制,后续再对该局部变量内容的更改不会影响Block中存储的切片值。因为block的内存结构中有一个结构体variables,外部局部变量被复制到了这个结构体中。
当block中需要修改外部局部变量时,需要给外部局部变量加__block修饰符。block就不再对该局部变量复制到结构体中,而是引用该外部局部变量。
- 3.3 使用时的注意点
使用block需要注意循环引用问题,解决办法是把引用的一方用__weak修饰,改变为弱指针。
ARC中,block不再存储在栈中,因此只有两种类型:全局静态和堆block。因为ARC可以通过编译器特性和运行时很好的处理对象内存,把所有对象都放到堆管理更加方便。