a) Objective-C是一门动态性比较强的编程语言,跟C、C++等语言有着很大的不同
1) C、C++都是 编写代码-->编译连接-->运行
2) 而OC则可以在运行的时候动态的去修改,例如动态的去调用自身类或者其他类的方法,或者增加、交换方法的实现
b) Objective-C的动态性是由Runtime API来支撑的
c) Runtime API提供的接口基本都是C语言的,源码由C\C++\汇编语言编写
a) 要想学习Runtime,首先要了解它底层的一些常用数据结构,比如isa指针
b) 在arm64架构之前,isa就是一个普通的指针,存储着Class、Meta-Class对象的内存地址
c) 从arm64架构开始,对isa进行了优化,变成了一个共用体(union)结构,还使用位域来存储更多的信息
d)64位之前isa就是Class类型,是isa_t类型
e) isa详解-位域
4.Class的结构
a) 类对象/元类对象的地址值最后三位都是0,因为isa底层原理
b) 一开始是只有class_ro_t,然后创建class_rw_t并且拷贝class_ro_t的内容,并且将bits指向class_rw_t
c) class_rw_t里面的methods、properties、protocols是二维数组,是可读可写的,包含了类的初始内容、分类的内容
c) 替换方法实现
1) class_replaceMethod
2) method_exchangeImplementations
9.Runtime API
a) 类
1) 动态创建一个类(参数:父类,类名,额外的内存空间)
1.1) Class objc_allocateClassPair(Class superclass,constchar*name, size_t extraBytes)2) 注册一个类(要在类注册之前添加成员变量)
2.1)voidobjc_registerClassPair(Class cls)3) 销毁一个类
3.1)voidobjc_disposeClassPair(Class cls)4) 获取isa指向的Class
4.1) Class object_getClass(id obj)5) 设置isa指向的Class
5.1) Class object_setClass(id obj, Class cls)6) 判断一个OC对象是否为Class
6.1) BOOL object_isClass(id obj)7) 判断一个Class是否为元类
7.1) BOOL class_isMetaClass(Class cls)8) 获取父类
8.1) Class class_getSuperclass(Class cls)
b) 成员变量
1) 获取一个实例变量信息
1.1) Ivar class_getInstanceVariable(Class cls,constchar*name)2) 拷贝实例变量列表(最后需要调用free释放)
2.1) Ivar *class_copyIvarList(Class cls,unsignedint*outCount)3) 设置和获取成员变量的值
3.1)voidobject_setIvar(id obj, Ivar ivar, id value)3.2) id object_getIvar(id obj, Ivar ivar)4) 动态添加成员变量(已经注册的类是不能动态添加成员变量的)
4.1) BOOL class_addIvar(Class cls,constchar* name, size_t size, uint8_t alignment,constchar* types)5) 获取成员变量的相关信息
5.1)constchar*ivar_getName(Ivar v)5.2)constchar*ivar_getTypeEncoding(Ivar v)
c) 属性
1) 获取一个属性
1.1) objc_property_t class_getProperty(Class cls,constchar*name)2) 拷贝属性列表(最后需要调用free释放)
2.1) objc_property_t *class_copyPropertyList(Class cls,unsignedint*outCount)3) 动态添加属性
3.1) BOOL class_addProperty(Class cls,constchar*name,const objc_property_attribute_t *attributes,unsignedint attributeCount)4) 动态替换属性
4.1)voidclass_replaceProperty(Class cls,constchar*name,const objc_property_attribute_t *attributes,unsignedint attributeCount)5) 获取属性的一些信息
5.1)constchar*property_getName(objc_property_t property)5.2)constchar*property_getAttributes(objc_property_t property)
d) 方法
1) 获得一个实例方法、类方法
1.1) Method class_getInstanceMethod(Class cls, SEL name)1.2) Method class_getClassMethod(Class cls, SEL name)2) 方法实现相关操作
2.1) IMP class_getMethodImplementation(Class cls, SEL name)2.2) IMP method_setImplementation(Method m, IMP imp)2.3)voidmethod_exchangeImplementations(Method m1, Method m2)3) 拷贝方法列表(最后需要调用free释放)
3.1) Method *class_copyMethodList(Class cls,unsignedint*outCount)4) 动态添加方法
4.1) BOOL class_addMethod(Class cls, SEL name, IMP imp,constchar*types)5) 动态替换方法
5.1) IMP class_replaceMethod(Class cls, SEL name, IMP imp,constchar*types)6) 获取方法的相关信息(带有copy的需要调用free去释放)
6.1) SEL method_getName(Method m)6.2) IMP method_getImplementation(Method m)6.3)constchar*method_getTypeEncoding(Method m)6.4)unsignedintmethod_getNumberOfArguments(Method m)6.5)char*method_copyReturnType(Method m)6.6)char*method_copyArgumentType(Method m,unsignedint index)7) 选择器相关
7.1)constchar*sel_getName(SEL sel)7.2) SEL sel_registerName(constchar*str)8) 用block作为方法实现
8.1) IMP imp_implementationWithBlock(id block)8.2) id imp_getBlock(IMP anImp)8.3) BOOL imp_removeBlock(IMP anImp)
10.其它知识点总结
a) objc_msgSendSuper 和 objc_msgSendSuper2区别
b) 数组可以当成指针来用
c) 分类的方法尽量+属于自己的前缀区分,万一覆盖了呢
d) 方法替换:替换系统的方法 例如拦截整个项目中所有按钮的点击事件
e) hook:钩子函数 拦截系统的方法 塞入自己的实现
f) 类簇(cu):我们看到的类型不一定是他的真实类型 NSString、NSArray、NSDictionary,真实类型是其他类型
g) 转成底层代码的方式
1) 转成cpp文件(作为参考)2) 程序运行起来查看汇编
3) 转成汇编
11.面试题1
a) isKindOfClass // 传入的对象的类对象是否==判断的类对象或者他的子类
b) isMemberOfClass // 传入的对象的类对象是否==判断的类对象
c)super class的返回类型是谁取决于方法调用者是谁即:消息接收者 消息接收者仍然是子类对象,只不过从父类的方法开始寻找方法
c) 底层实现原理
12.面试题2
a) 函数调用堆栈的问题
1) 局部变量分配在栈空间
2) 栈空间分配,从高地址到低地址
b) 寄存器(存储在cpu里面,相当于一个元件,参数都是存储在这里面)比内存的效率更高