一、objc.h
objc.h中定义的几个基本类型
名称 | 类型 |
---|---|
Class | struct objc_class * 不开源的结构体指针,注意不要和runtime.h中objc_class弄混,这两个不是一个东西 |
id | struct objc_class* (具体结构看下面) |
SEL | struct objc_selector* 不开源的结构体指针 |
IMP | void (*IMP)(void /* id, SEL, ... */ ) 或id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...) |
BOOL | bool 或signed char |
objc_object
具体结构
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
好了,有了这些最基本的东西,看一下文件中的API
方法 | 作用 |
---|---|
1.const char * _Nonnull sel_getName(SEL _Nonnull sel) |
根据SEL 获取C string |
2.SEL _Nonnull sel_registerName(const char * _Nonnull str) |
通过C string向runtime系统中注册一个方法 |
3.const char * _Nonnull object_getClassName(id _Nullable obj) |
获取一个事例对象的类名 |
4.void * _Nullable object_getIndexedIvars(id _Nullable obj) |
获取一个实例对象的变量 |
5.BOOL sel_isMapped(SEL _Nonnull sel) |
验证一个SEL 是否有实际函数内容,即是否有一个IMP 指针对应这个SEL |
6.SEL _Nonnull sel_getUid(const char * _Nonnull str) |
通过C string向runtime系统中注册一个方法 |
二、runtime.h
首先了解一件事情,对于一般的OC开发,开发人员做的工作就是创建类,类中包含方法(实例方法、类方法)、实例变量、属性,在类的基础上延伸出分类、代理等,接下来就是通过类或者实例调用方法做一系列操作,OC所谓的动态型语言,就是可以动态对类中的各种东西进行调整,通过runtime.h中提供的方法
runtime定义了下面这些基本类型
名称 | 类型 |
---|---|
Method | struct objc_method * 不开源的结构体指针 |
Ivar | struct objc_ivar * 不开源的结构体指针 |
Category | objc_category * 不开源的结构体指针 |
objc_property_t | struct objc_property * 不开源的结构体指针 |
objc_class | 结构体 |
Protocol | class或struct objc_object objc.h中定义的该类型 |
objc_method_description | 结构体 |
objc_property_attribute_t | 结构体 |
关于方法有一些提示
- SEL:方法选择器。不同类中相同名字的方法所对应的 selector 是相同的。
- IMP:方法实现。是一个函数指针,指向方法的实现。
- Method:方法的结构体,其中应该保存了方法的名字,实现和类型描述字符串等信息
三、runtime API
runtime的API分为几类,这样更容易理解和记忆
1.对象的操作
1.复制对象
object_copy
ARC下不可用
2.销毁对象object_dispose
ARC下不可用
3.获取一个对象的类object_getClass
4.给一个对象设置新的类object_setClass
5.检验一个对象是否是类对象object_isClass
6.获取一个对象的实例变量object_getIvar
7.设置一个对象的实例变量object_setIvar
8.给一个对象的某个实例变量赋值object_setIvarWithStrongDefault
9.修改一个对象的某个实例变量的值object_setInstanceVariable
10.修改一个对象的某个实例变量的值object_setInstanceVariableWithStrongDefault
不同于9的是内存管理方式不同
11.获取一个对象的某个实例变量的值object_getInstanceVariable
2.类的操作
1.通过字符查找某个类
objc_getClass
2.通过字符查找某各类的元类objc_getMetaClass
3.通过字符查找某个类objc_lookUpClass
和1不同之处在于,1方法若没找到类,会创建一个,该方法不会创建
4.通过字符查找某个类objc_getRequiredClass
和1的不同之处在于,如果该方法没找到类,将会杀掉进程
5.获取已注册的类列表objc_getClassList
6.获取已注册的类的指针列表objc_copyClassList
7.获取类的名字class_getName
8.验证是否为元类class_isMetaClass
9.获取类的父类class_getSuperclass
10.设置类的父类class_setSuperclass
官方不推荐使用
11.获取类的版本信息class_getVersion
12.设置类的版本信息class_setVersion
13.获取类的大小class_getInstanceSize
14.通过字符获取类的某个实例变量class_getInstanceVariable
15.通过字符获取类的某个实例变量class_getClassVariable
16.获取类的实例变量列表class_copyIvarList
17.通过字符获取类的某个方法class_getInstanceMethod
18.通过字符获取类的某个方法class_getClassMethod
19.获取类的某个方法的IMPclass_getMethodImplementation
20.获取类的某个方法的IMPclass_getMethodImplementation_stret
21.判断类是否相应某个方法class_respondsToSelector
22.获取类的方法列表class_copyMethodList
23.判断类是否遵循某个代理class_conformsToProtocol
24.获取类的代理列表class_copyProtocolList
25.通过字符获取类的某个属性class_getProperty
26.获取类的属性列表class_copyPropertyList
27.获取强引用的静态变量class_getIvarLayout
一般不用,该值由运行时决定
28.获取弱引用的静态变量class_getWeakIvarLayout
29.给类添加方法class_addMethod
30.替换类的指定方法的IMPclass_replaceMethod
31.类添加实例变量class_addIvar
32.类添加代理class_addProtocol
33.类添加代理class_addProtocol
和32的参数不同
34.替换类的代理class_replaceProperty
35.设置强引用的静态变量class_getIvarLayout
一般不用,该值由运行时决定
36.设置弱引用的静态变量class_getWeakIvarLayout
37.获取类的实例objc_getFutureClass
不可以自己调用,一般用于桥接
3.实例的操作
1.创建一个类的实例
class_createInstance
2.在指定内存创建一个类的实例objc_constructInstance
不可以自己调用
2.销毁指定内存创建的实例objc_destructInstance
不可以自己调用
4.类的添加操作
1.创建一个类和元类
objc_allocateClassPair
2.在系统中注册一个类objc_registerClassPair
类被创建并不能直接只用,注册后可以
3.检查类是否重复objc_duplicateClass
不可以自己调用
4.销毁一个类和袁磊objc_disposeClassPair
如果存在类的实例,不要调用该方法
5.Method相关操作
1.获取Method名称
method_getName
2.获取Method的IMP指针method_getImplementation
3.获取Method的TypeEncodingmethod_getTypeEncoding
参数返回值等描述信息
4.获取Method的参数个数method_getNumberOfArguments
5.获取Method的返回值描述method_copyReturnType
6.获取Method的某个参数的描述method_copyArgumentType
7.获取Method的返回值描述method_getReturnType
和5不同的是,5返回的信息用完需要用free()释放
8.获取Method的某个参数的描述method_getArgumentType
9.获取Method的构建描述method_getDescription
返回值是objc_method_description结构体
10.设置Method的IMP指针method_setImplementation
11.交换Method的IMP指针method_exchangeImplementations
6.对实例变量的操作
1.获取实例变量名称
ivar_getName
2.获取实例变量的TypeEncodingivar_getTypeEncoding
3.获取实例变量的内存偏移量ivar_getOffset
7.对属性的操作
1.获取属性名
property_getName
2.获取属性的特性property_getAttributes
3.获取属性的特性列表property_copyAttributeList
4.获取属性的特性值property_copyAttributeValue
8.对代理的操作
1.通过字符串创建一个代理
objc_getProtocol
2.获取到当前的所有代理objc_copyProtocolList
3.判断一个代理是否继承于另外一个代理protocol_conformsToProtocol
4.用于判断是否是同一个代理protocol_isEqual
5.获取代理的名称protocol_getName
6.获取代理中某个方法的描述protocol_getMethodDescription
7.获取代理的所有方法描述protocol_copyMethodDescriptionList
8.获取代理的某个属性protocol_getProperty
9.获取代理的所有属性protocol_copyPropertyList
10.获取代理的所有属性protocol_copyPropertyList2
和9不同的是多了条件参数
11.获取当前代理继承的那些代理protocol_copyProtocolList
12.通过字符串创建一个代理objc_allocateProtocol
13.注册一个代理objc_registerProtocol
代理被创建后不能直接调用,注册后才可使用
14.给代理添加方法protocol_addMethodDescription
15.给代理添加另外一个代理的方法protocol_addProtocol
16.给代理添加属性protocol_addProperty
9.对库的操作
1.返货OC加载的所有库的描述
objc_copyImageNames
2.获取一个类属于哪个库class_getImageName
3.获取一个库的所有类名objc_copyClassNamesForImage
10.对Selectors的操作
1.获取SEL的名字
sel_getName
2.向系统中注册一个SELsel_registerName
3.判断另个SEL是否相同sel_isEqual
等效于==
11.OC语言特性
1.如果遍历一个对象是,该对象被改变会通过该方法抛出异常
objc_enumerationMutation
该方法由编译器调用
2.设置处理异常函数objc_setEnumerationMutationHandler
当1抛出异常时,可通过该方法设置处理异常的函数
3.设置消息转发(objc_msgForward)时的处理函数objc_setForwardHandler
4.创建一个IMP指针,指向一个代码块imp_implementationWithBlock
5.获取IMP指针的代码块imp_getBlock
该IMP指针必须是imp_implementationWithBlock创建的
6.释放一个IMP指针的代码块imp_removeBlock
该IMP指针必须是imp_implementationWithBlock创建的
7.返回一个弱指针指向的对象objc_loadWeak
通常__weak修饰的
8.给弱指针赋一个新的值objc_storeWeak
12.关联策略
1.给对象设置关联属性
objc_setAssociatedObject
2.获取关联对象objc_getAssociatedObject
3.移除关联属性objc_removeAssociatedObjects
四、runtime相对来说常用的方法
1.Class
方法 | 返回值 | 作用 |
---|---|---|
objc_allocateClassPair(Class _Nullable superclass, const char * _Nonnull name, size_t extraBytes) |
Class |
创建新Class,开辟空间 |
objc_registerClassPair(Class _Nonnull cls) |
void |
向系统注册上面创建的Class |
object_getClass(id _Nullable obj) |
Class |
通过id 获取Class |
object_setClass(id _Nullable obj, Class _Nonnull cls) |
Class |
给一个id 复制新类,并返回原类 |
object_isClass(id _Nullable obj) |
BOOL |
如果id 是类或元类则返回YES,其他返回NO |
objc_getClass(const char * _Nonnull name) |
Class |
检查一个类是否在runtime中注册,如果注册则返回该类,不存在返回nil,类似方法还有objc_lookUpClass 和objc_getRequiredClass |
objc_getMetaClass(const char * _Nonnull name) |
Class |
检查一个类是否在runtime中注册,如果注册则返回该类的元类,不存在返回nil |
const char * _Nonnull class_getName(Class _Nullable cls) |
char * |
获取类名 |
class_isMetaClass(Class _Nullable cls) |
BOOL |
判断是否是元类 |
class_getSuperclass(Class _Nullable cls) |
Class |
获取父类 |
class_getVersion(Class _Nullable cls) |
int |
获取class version |
class_setVersion(Class _Nullable cls, int version) |
void |
设置class version |
2.Method
方法 | 返回值 | 作用 |
---|---|---|
class_getInstanceMethod(Class _Nullable cls, SEL _Nonnull name) |
Method |
获取Method |
class_getClassMethod(Class _Nullable cls, SEL _Nonnull name) |
Method |
获取Method |
class_copyMethodList(Class _Nullable cls, unsigned int * _Nullable outCount) |
Method |
获取全部Method |
class_addMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types) |
BOOL |
添加Method |
class_replaceMethod(Class _Nullable cls, SEL _Nonnull name, IMP _Nonnull imp, const char * _Nullable types) |
IMP |
修改某个Method |
method_getName(Method _Nonnull m) |
SEL |
获取方法的签名SEL,如果想获得字符串名称要用sel_getName(method_getName(method)) |
method_getImplementation(Method _Nonnull m) |
IMP |
获取IMP |
method_getTypeEncoding(Method _Nonnull m) |
char * |
获取方法typeEncoding |
method_getNumberOfArguments(Method _Nonnull m) |
unsigned int |
获取方法参数个数 |
method_copyReturnType(Method _Nonnull m) |
char * |
获取方法返回值类型 |
method_copyArgumentType(Method _Nonnull m, unsigned int index) |
char * |
获取方法参数类型 |
method_getReturnType(Method _Nonnull m, char * _Nonnull dst, size_t dst_len) |
void |
获取方法返回值类型 |
method_getArgumentType(Method _Nonnull m, unsigned int index, char * _Nullable dst, size_t dst_len) |
void |
获取方法参数类型 |
method_getDescription(Method _Nonnull m) |
struct objc_method_description * |
获取方法的objc_method_description |
method_setImplementation(Method _Nonnull m, IMP _Nonnull imp) |
IMP |
设置方法的IMP |
method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2) |
void |
交换方法的IMP |
3.SEL
方法 | 返回值 | 作用 |
---|---|---|
sel_getName(SEL _Nonnull sel) |
char * |
获取SEL名称 |
sel_registerName(const char * _Nonnull str) |
SEL |
创建并向系统注册一个SEL |
sel_isEqual(SEL _Nonnull lhs, SEL _Nonnull rhs) |
BOOL |
是否相等 |
4.Ivar
方法 | 返回值 | 作用 |
---|---|---|
class_getInstanceVariable(Class _Nullable cls, const char * _Nonnull name) |
Ivar |
获取实例的某个变量 |
class_getClassVariable(Class _Nullable cls, const char * _Nonnull name) |
Ivar |
获取类的某个变量 |
class_copyIvarList(Class _Nullable cls, unsigned int * _Nullable outCount) |
Ivar * |
获取变量列表 |
class_getIvarLayout(Class _Nullable cls) |
uint8_t * |
获取Ivar的内存布局 |
class_getWeakIvarLayout(Class _Nullable cls) |
uint8_t * |
同上,不同点是以weak修饰为标准 |
class_setIvarLayout(Class _Nullable cls, const uint8_t * _Nullable layout) |
void |
设置Ivar内存布局 |
class_setWeakIvarLayout(Class _Nullable cls, const uint8_t * _Nullable layout) |
void |
同上,不同点是以weak修饰为标准 |
class_addIvar(Class _Nullable cls, const char * _Nonnull name, size_t size, uint8_t alignment, const char * _Nullable types) |
BOOL |
添加实例变量 |
ivar_getName(Ivar _Nonnull v) |
const char * |
获取变量名称 |
ivar_getTypeEncoding(Ivar _Nonnull v) |
const char * |
获取变量TypeEncoding |
ivar_getOffset(Ivar _Nonnull v) |
ptrdiff_t |
获取变量的内存地址偏移量 |
5.IMP
方法 | 返回值 | 作用 |
---|---|---|
class_getMethodImplementation(Class _Nullable cls, SEL _Nonnull name) |
IMP |
获取IMP class_getMethodImplementation may be faster than method_getImplementation(class_getInstanceMethod(cls, name)) |
imp_implementationWithBlock(id _Nonnull block) |
IMP |
用block创建一个IMP |
imp_getBlock(IMP _Nonnull anImp) |
id |
获取block,必须是用imp_implementationWithBlock创建的IMP |
imp_removeBlock(IMP _Nonnull anImp) |
void |
释放创建IMP的block |
5.Protocol
方法 | 返回值 | 作用 |
---|---|---|
class_copyProtocolList(Class _Nullable cls, unsigned int * _Nullable outCount) |
Protocol * |
获取代理列表 |
class_addProtocol(Class _Nullable cls, Protocol * _Nonnull protocol) |
BOOL |
添加代理 |
objc_getProtocol(const char * _Nonnull name) |
Protocol * |
获取代理 |
objc_copyProtocolList(unsigned int * _Nullable outCount) |
Protocol * |
获取所有代理 |
protocol_conformsToProtocol(Protocol * _Nullable proto, Protocol * _Nullable other) |
BOOL |
代理是否遵循另外一个代理 |
protocol_isEqual(Protocol * _Nullable proto, Protocol * _Nullable other) |
BOOL |
代理是否相等 |
protocol_getName(Protocol * _Nonnull proto) |
const char * |
获取代理名称 |
protocol_getMethodDescription(Protocol * _Nonnull proto, SEL _Nonnull aSel, BOOL isRequiredMethod, BOOL isInstanceMethod) |
struct objc_method_description |
获取代理某个方法的objc_method_description |
protocol_copyMethodDescriptionList(Protocol * _Nonnull proto, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int * _Nullable outCount) |
struct objc_method_description * |
获取代理的所有方法的objc_method_description |
protocol_getProperty(Protocol * _Nonnull proto, const char * _Nonnull name, BOOL isRequiredProperty, BOOL isInstanceProperty) |
objc_property_t |
获取代理的某个属性 |
protocol_copyPropertyList(Protocol * _Nonnull proto, unsigned int * _Nullable outCount) |
objc_property_t * |
获取代理的全部属性 |
protocol_copyPropertyList2(Protocol * _Nonnull proto, unsigned int * _Nullable outCount, BOOL isRequiredProperty, BOOL isInstanceProperty) |
objc_property_t * |
获取代理的全部属性,多了选择条件 |
protocol_copyProtocolList(Protocol * _Nonnull proto, unsigned int * _Nullable outCount) |
Protocol * * |
获取一个代理遵循了那些代理 |
objc_allocateProtocol(const char * _Nonnull name) |
Protocol * |
创建一个Protocol,开辟空间 |
objc_registerProtocol(Protocol * _Nonnull proto) |
void |
向系统注册Protocol |
protocol_addMethodDescription(Protocol * _Nonnull proto, SEL _Nonnull name, const char * _Nullable types, BOOL isRequiredMethod, BOOL isInstanceMethod) |
void |
给代理添加Method |
protocol_addProtocol(Protocol * _Nonnull proto, Protocol * _Nonnull addition) |
void |
给代理添加遵循的代理 |
protocol_addProperty(Protocol * _Nonnull proto, const char * _Nonnull name, const objc_property_attribute_t * _Nullable attributes, unsigned int attributeCount, BOOL isRequiredProperty, BOOL isInstanceProperty) |
void |
给代理添加属性 |
6.objc_property_t
方法 | 返回值 | 作用 |
---|---|---|
class_getProperty(Class _Nullable cls, const char * _Nonnull name) |
objc_property_t |
获取某个属性 |
class_copyPropertyList(Class _Nullable cls, unsigned int * _Nullable outCount) |
objc_property_t * |
获取某个属性 |
class_addProperty(Class _Nullable cls, const char * _Nonnull name, const objc_property_attribute_t * _Nullable attributes, unsigned int attributeCount) |
BOOL |
添加属性 |
class_replaceProperty(Class _Nullable cls, const char * _Nonnull name, const objc_property_attribute_t * _Nullable attributes, unsigned int attributeCount) |
void |
替换属性 |
property_getName(objc_property_t _Nonnull property) |
const char * |
获取属性名 |
property_getAttributes(objc_property_t _Nonnull property) |
const char * |
获取属性特性 |
property_copyAttributeList(objc_property_t _Nonnull property, unsigned int * _Nullable outCount) |
objc_property_attribute_t * |
获取objc_property_attribute_t |
property_copyAttributeValue(objc_property_t _Nonnull property, const char * _Nonnull attributeName) |
char * |
获取属性的objc_property_attribute_t的values |
7.对库操作
方法 | 返回值 | 作用 |
---|---|---|
objc_copyImageNames(unsigned int * _Nullable outCount) |
const char * * |
获取OC中的加载的库名 |
class_getImageName(Class _Nullable cls) |
const char * |
根据Class获取库名 |
objc_copyClassNamesForImage(const char * _Nonnull image, unsigned int * _Nullable outCount) |
const char * * |
获取一个库中的所有类名 |
8.其他
方法 | 返回值 | 作用 |
---|---|---|
class_createInstance(Class _Nullable cls, size_t extraBytes) |
id |
创建实例对象 |
objc_loadWeak(id _Nullable * _Nonnull location) |
id |
加载一个弱指针指向的对象,并可以持有,一般加载__weak修饰的对象 |
objc_storeWeak(id _Nullable * _Nonnull location, id _Nullable obj) |
id |
给弱指针指的对象重新赋值 |
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy) |
void |
关联对象 |
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key) |
id |
获取关联的对象 |
objc_removeAssociatedObjects(id _Nonnull object) |
void |
回复关联原始状态,通常不应该被调用,若想移除某个关联属性,应该用objc_setAssociatedObject赋值nil,而不应该调用该方法,该方法会将所有关联回复到出事状态 |
objc_enumerationMutation(id _Nonnull obj) |
void |
一个对象在执行foreach循环是,如果修改了自身会出错,如果调用该方法,当修改自身时可设置处理函数 |
objc_setEnumerationMutationHandler(void (*_Nullable handler)(id _Nonnull )) |
void |
设置的处理函数 |
objc_setForwardHandler(void * _Nonnull fwd, void * _Nonnull fwd_stret) |
void |
当触发objc_msgForward或objc_msgForward_stret时设置触发函数 |