一、objc库

一、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 boolsigned 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_objectobjc.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_lookUpClassobjc_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时设置触发函数
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容