Objective-C Runtime是提供Objective-C语言动态特性的运行时的库。
/* Types */
#if !OBJC_TYPES_DEFINED
// 类方法
typedef struct objc_method *Method;
// 实例变量
typedef struct objc_ivar *Ivar;
// 分类
typedef struct objc_category *Category;
// 对象声明的属性
typedef struct objc_property *objc_property_t;
// objc_class结构体
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE; // 父类
const char *name OBJC2_UNAVAILABLE; // 类名
long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE; // 类信息,供运行期使用的一些位标识
long instance_size OBJC2_UNAVAILABLE; // 该类的实例变量大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 该类的成员变量链表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法定义的链表
struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
#endif
} OBJC2_UNAVAILABLE;
#endif
#ifdef __OBJC__
@class Protocol;
#else
typedef struct objc_object Protocol;
#endif
// 定义方法
struct objc_method_description {
SEL name; // 方法的名称
char *types; // 方法的参数类型
};
// 定义属性
typedef struct {
const char *name; // 属性名称
const char *value; // 属性值
} objc_property_attribute_t;
/* 实例方法 */
// 返回指定对象的一个副本
OBJC_EXPORT id object_copy(id obj, size_t size);
// 释放指定对象内存 返回nil
OBJC_EXPORT id object_dispose(id obj);
// 返回对象的类
OBJC_EXPORT Class object_getClass(id obj);
// 设置对象的类
OBJC_EXPORT Class object_setClass(id obj, Class cls);
// 是否是类对象
OBJC_EXPORT BOOL object_isClass(id obj);
// 返回给定对象的类名
OBJC_EXPORT const char *object_getClassName(id obj);
// 返回指向给定对象分配的任何额外字节的指针
OBJC_EXPORT void *object_getIndexedIvars(id obj);
// 返回对象中实例变量的值
OBJC_EXPORT id object_getIvar(id obj, Ivar ivar);
// 设置对象中实例变量的值
OBJC_EXPORT void object_setIvar(id obj, Ivar ivar, id value);
// 在对象中设置实例变量的值 iOS 10 AVAILABLE
OBJC_EXPORT void object_setIvarWithStrongDefault(id obj, Ivar ivar, id value);
// 修改类实例的实例变量的值
OBJC_EXPORT Ivar object_setInstanceVariable(id obj, const char *name, void *value);
// 更改一个实例类中实例变量的值 iOS 10 AVAILABLE
OBJC_EXPORT Ivar object_setInstanceVariableWithStrongDefault(id obj, const char *name, void *value);
// 返回对象实例变量的值
OBJC_EXPORT Ivar object_getInstanceVariable(id obj, const char *name, void **outValue);
/* 类方法 */
// 返回指定的类
OBJC_EXPORT Class objc_getClass(const char *name);
// 返回指定的元类
OBJC_EXPORT Class objc_getMetaClass(const char *name);
// 返回指定的类
OBJC_EXPORT Class objc_lookUpClass(const char *name);
// 返回指定的类
OBJC_EXPORT Class objc_getRequiredClass(const char *name);
// 返回已注册的类定义的列表
OBJC_EXPORT int objc_getClassList(Class *buffer, int bufferCount);
// 创建并返回一个指向所有已注册类的指针列表
OBJC_EXPORT Class *objc_copyClassList(unsigned int *outCount);
// 返回类的类名
OBJC_EXPORT const char *class_getName(Class cls);
// 是否是元类
OBJC_EXPORT BOOL class_isMetaClass(Class cls);
// 返回类的父类
OBJC_EXPORT Class class_getSuperclass(Class cls);
// 给类指定一个父类
OBJC_EXPORT Class class_setSuperclass(Class cls, Class newSuper);
// 返回类版本号
OBJC_EXPORT int class_getVersion(Class cls);
// 设置类版本号
OBJC_EXPORT void class_setVersion(Class cls, int version);
// 返回实例类的大小
OBJC_EXPORT size_t class_getInstanceSize(Class cls);
// 返回类中指定名称实例成员变量的信息
OBJC_EXPORT Ivar class_getInstanceVariable(Class cls, const char *name);
// 返回类成员变量的信息
OBJC_EXPORT Ivar class_getClassVariable(Class cls, const char *name);
// 返回整个成员变量列表
OBJC_EXPORT Ivar *class_copyIvarList(Class cls, unsigned int *outCount);
// 返回实例方法
OBJC_EXPORT Method class_getInstanceMethod(Class cls, SEL name);
// 返回类方法
OBJC_EXPORT Method class_getClassMethod(Class cls, SEL name);
// 返回类方法实现的指针
OBJC_EXPORT IMP class_getMethodImplementation(Class cls, SEL name);
// 返回类方法实现的指针
OBJC_EXPORT IMP class_getMethodImplementation_stret(Class cls, SEL name);
// 类实例是否响应指定的selector
OBJC_EXPORT BOOL class_respondsToSelector(Class cls, SEL sel);
// 返回所有方法的数组
OBJC_EXPORT Method *class_copyMethodList(Class cls, unsigned int *outCount);
// 返回类是否实现指定的协议
OBJC_EXPORT BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
// 返回类实现的协议列表
OBJC_EXPORT Protocol * __unsafe_unretained
*class_copyProtocolList(Class cls, unsigned int *outCount);
// 返回指定的属性
OBJC_EXPORT objc_property_t class_getProperty(Class cls, const char *name);
// 返回属性列表
OBJC_EXPORT objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount);
// 返回指定变量布局
OBJC_EXPORT const uint8_t *class_getIvarLayout(Class cls);
// 返回指定弱引用的变量布局
OBJC_EXPORT const uint8_t *class_getWeakIvarLayout(Class cls);
// 添加方法 如果返回YES则添加成功
OBJC_EXPORT BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);
// 替代方法的实现
OBJC_EXPORT IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
// 添加变量
OBJC_EXPORT BOOL class_addIvar(Class cls, const char *name, size_t size,uint8_t alignment, const char *types);
// 添加协议
OBJC_EXPORT BOOL class_addProtocol(Class cls, Protocol *protocol);
// 添加属性
OBJC_EXPORT BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
// 替换属性
OBJC_EXPORT void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
// 设置变量布局
OBJC_EXPORT void class_setIvarLayout(Class cls, const uint8_t *layout);
// 设置弱属性的变量布局
OBJC_EXPORT void class_setWeakIvarLayout(Class cls, const uint8_t *layout);
// 通过CoreFoundation's自由连接。不能自己调用此方法
OBJC_EXPORT Class objc_getFutureClass(const char *name);
// 创建类实例
OBJC_EXPORT id class_createInstance(Class cls, size_t extraBytes);
// 在指定位置创建类实例
OBJC_EXPORT id objc_constructInstance(Class cls, void *bytes);
// 销毁类实例
OBJC_EXPORT void *objc_destructInstance(id obj);
// 创建新的类
OBJC_EXPORT Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
// 注册创建的类
OBJC_EXPORT void objc_registerClassPair(Class cls);
// 用于KVO观察者模式。 不能自己调用此方法
OBJC_EXPORT Class objc_duplicateClass(Class original, const char *name, size_t extraBytes);
// 销毁一个类及其相关联的类
OBJC_EXPORT void objc_disposeClassPair(Class cls);
// 返回方法的名称
OBJC_EXPORT SEL method_getName(Method m);
// 返回一个方法指针
OBJC_EXPORT IMP method_getImplementation(Method m);
// 返回描述方法的字符串
OBJC_EXPORT const char *method_getTypeEncoding(Method m);
// 返回方法接收参数的个数
OBJC_EXPORT unsigned int method_getNumberOfArguments(Method m);
// 返回描述方法返回类型的字符串
OBJC_EXPORT char *method_copyReturnType(Method m);
// 返回描述方法单个参数类型的字符串
OBJC_EXPORT char *method_copyArgumentType(Method m, unsigned int index);
// 返回一个描述方法返回类型
OBJC_EXPORT void method_getReturnType(Method m, char *dst, size_t dst_len);
// 返回描述方法单个参数类型
OBJC_EXPORT void method_getArgumentType(Method m, unsigned int index, char *dst, size_t dst_len);
// 返回指定方法的结构描述
OBJC_EXPORT struct objc_method_description *method_getDescription(Method m);
// 设置方法的指针地址
OBJC_EXPORT IMP method_setImplementation(Method m, IMP imp);
/**
* 交换两个方法指针地址
* @note 交换原理如下:
* \code
* IMP imp1 = method_getImplementation(m1);
* IMP imp2 = method_getImplementation(m2);
* method_setImplementation(m1, imp2);
* method_setImplementation(m2, imp1);
* \endcode
*/
OBJC_EXPORT void method_exchangeImplementations(Method m1, Method m2);
// 返回实例变量的名称
OBJC_EXPORT const char *ivar_getName(Ivar v);
// 返回实例变量类型的字符串
OBJC_EXPORT const char *ivar_getTypeEncoding(Ivar v);
// 返回实例变量的偏移量
OBJC_EXPORT ptrdiff_t ivar_getOffset(Ivar v);
// 返回
OBJC_EXPORT const char *property_getName(objc_property_t property);
// 返回属性的属性字符串
OBJC_EXPORT const char *property_getAttributes(objc_property_t property);
// 返回属性的属性数组
OBJC_EXPORT objc_property_attribute_t *property_copyAttributeList(objc_property_t property, unsigned int *outCount);
// 返回指定属性名称的属性的值
OBJC_EXPORT char *property_copyAttributeValue(objc_property_t property, const char *attributeName);
// 返回协议的名称
OBJC_EXPORT Protocol *objc_getProtocol(const char *name);
// 返回runtime已知的所有协议的数组
OBJC_EXPORT Protocol * __unsafe_unretained *objc_copyProtocolList(unsigned int *outCount);
// 判断一个协议是否遵循了另一个协议
OBJC_EXPORT BOOL protocol_conformsToProtocol(Protocol *proto, Protocol *other);
// 判断两个协议是否相等
OBJC_EXPORT BOOL protocol_isEqual(Protocol *proto, Protocol *other);
// 返回协议的名称
OBJC_EXPORT const char *protocol_getName(Protocol *p);
// 返回执行协议指定方法结构的描述
OBJC_EXPORT struct objc_method_description protocol_getMethodDescription(Protocol *p, SEL aSel, BOOL isRequiredMethod, BOOL isInstanceMethod);
// 返回满足指定协议方法描述的数组
OBJC_EXPORT struct objc_method_description *protocol_copyMethodDescriptionList(Protocol *p, BOOL isRequiredMethod, BOOL isInstanceMethod, unsigned int *outCount);
// 返回指定协议的属性
OBJC_EXPORT objc_property_t protocol_getProperty(Protocol *proto, const char *name, BOOL isRequiredProperty, BOOL isInstanceProperty);
/**
* 返回声明协议所需要的属性的数组.
* @note Identical to
* \code
* protocol_copyPropertyList2(proto, outCount, YES, YES);
* \endcode
*/
OBJC_EXPORT objc_property_t *protocol_copyPropertyList(Protocol *proto, unsigned int *outCount);
OBJC_EXPORT objc_property_t *protocol_copyPropertyList2(Protocol *proto, unsigned int *outCount, BOOL isRequiredProperty, BOOL isInstanceProperty)
OBJC_AVAILABLE(10.12, 10.0, 10.0, 3.0);
// 返回协议所采用的协议的数组
OBJC_EXPORT Protocol * __unsafe_unretained *protocol_copyProtocolList(Protocol *proto, unsigned int *outCount);
// 创建一个新的协议,添加到objc_registerProtocol方法中
OBJC_EXPORT Protocol *objc_allocateProtocol(const char *name);
// 注册新协议
OBJC_EXPORT void objc_registerProtocol(Protocol *proto);
// 添加一个方法到协议中,此协议必须正在建设中
OBJC_EXPORT void protocol_addMethodDescription(Protocol *proto, SEL name, const char *types, BOOL isRequiredMethod, BOOL isInstanceMethod);
// 把已经建设的协议添加到正在建设的协议中去
OBJC_EXPORT void protocol_addProtocol(Protocol *proto, Protocol *addition);
// 添加一个属性到协议中去,此协议必须正在建设中
OBJC_EXPORT void protocol_addProperty(Protocol *proto, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount, BOOL isRequiredProperty, BOOL isInstanceProperty);
// 返回所有加载在Objective-C框架和动态库上的名称
OBJC_EXPORT const char **objc_copyImageNames(unsigned int *outCount);
// 返回一个来自类动态库的名称
OBJC_EXPORT const char *class_getImageName(Class cls);
// 返回库中所有类的名称
OBJC_EXPORT const char **objc_copyClassNamesForImage(const char *image,unsigned int *outCount);
// 返回指定sel的方法的名称
OBJC_EXPORT const char *sel_getName(SEL sel);
// 注册一个Objective-C运行时系统的方法名称
OBJC_EXPORT SEL sel_getUid(const char *str);
// 注册一个sel方法,并映方法名称到sel中并返回sel值
OBJC_EXPORT SEL sel_registerName(const char *str);
// 判断两个sel是否相同
OBJC_EXPORT BOOL sel_isEqual(SEL lhs, SEL rhs);
// 当发现突变的foreach迭代过程中时插入编译器
OBJC_EXPORT void objc_enumerationMutation(id obj);
// 设置当前突变的处理程序
OBJC_EXPORT void objc_setEnumerationMutationHandler(void (*handler)(id));
// 设置函数调用objc_msgForward
OBJC_EXPORT void objc_setForwardHandler(void *fwd, void *fwd_stret);
// 创建一个当调用此方法时调用指定块的函数指针
OBJC_EXPORT IMP imp_implementationWithBlock(id block);
// 返回一个使用imp_implementationWithBlock创建的与块相关的函数指针
OBJC_EXPORT id imp_getBlock(IMP anImp);
// 移除与函数指针相关联的块
OBJC_EXPORT BOOL imp_removeBlock(IMP anImp);
// 加载弱指针引用的对象并返回它
OBJC_EXPORT id objc_loadWeak(id *location);
// 存储_weak变量的新值
OBJC_EXPORT id objc_storeWeak(id *location, id obj);
// 设置关联
OBJC_EXPORT void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
// 获取关联值
OBJC_EXPORT id objc_getAssociatedObject(id object, const void *key);
// 移除关联对象
OBJC_EXPORT void objc_removeAssociatedObjects(id object);
// 发送一个具有简单返回值的消息到一个实例类上
OBJC_EXPORT void objc_msgSend(void /* id self, SEL op, ... */ );
// 发送一个具有结构返回值的消息到一个实例类上
OBJC_EXPORT void objc_msgSendSuper(void /* struct objc_super *super, SEL op, ... */ );
// 发送一个具有返回数据结构值的消息到一个实例类上
OBJC_EXPORT void objc_msgSend_stret(void /* id self, SEL op, ... */ );
// 发送一个具有返回数据结构值的消息到一个实例父类上
OBJC_EXPORT void objc_msgSendSuper_stret(void /* struct objc_super *super, SEL op, ... */ );
// 发送一个具有返回浮点类型值的消息到一个实例类上
OBJC_EXPORT void objc_msgSend_fpret(void /* id self, SEL op, ... */ );
OBJC_EXPORT void objc_msgSend_fp2ret(void /* id self, SEL op, ... */ );
// 调用指定方法的实现
OBJC_EXPORT void method_invoke(void /* id receiver, Method m, ... */ );
// 调用返回数据结构的指定方法的实现
OBJC_EXPORT void method_invoke_stret(void /* id receiver, Method m, ... */ );
// 关联策略
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
OBJC_ASSOCIATION_ASSIGN = 0, // 表示弱引用关联,非线程安全,通常是数据类型
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 表示强(strong)引用关联对象,非线程安全
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, // 表示关联对象copy,非线程安全
OBJC_ASSOCIATION_RETAIN = 01401, // 表示强(strong)引用关联对象,是线程安全的
OBJC_ASSOCIATION_COPY = 01403 // 表示关联对象copy,是线程安全的
};
// 编码类型
#define _C_ID '@' // 代表对象类型
#define _C_CLASS '#' // 代表类对象 (Class)
#define _C_SEL ':' // 代表方法selector (SEL)
#define _C_CHR 'c' // 代表char类型
#define _C_UCHR 'C' // 代表unsigned char类型
#define _C_SHT 's' // 代表short类型
#define _C_USHT 'S' // 代表unsigned short类型
#define _C_INT 'i' // 代表int类型
#define _C_UINT 'I' // 代表unsigned int类型
#define _C_LNG 'l' // 代表long类型,在64位处理器上也是按照32位处理
#define _C_ULNG 'L' // 代表unsigned long类型
#define _C_LNG_LNG 'q' // 代表long long类型
#define _C_ULNG_LNG 'Q' // 代表unsigned long long类型
#define _C_FLT 'f' // 代表float类型
#define _C_DBL 'd' // 代表double类型
#define _C_BFLD 'b' //
#define _C_BOOL 'B' // 代表C++中的bool或者C99中的_Bool
#define _C_VOID 'v' // 代表void类型
#define _C_UNDEF '?' // 代表未知类型
#define _C_PTR '^' // 代表指针类型
#define _C_CHARPTR '*' // 代表字符串类型 (char *)
#define _C_ATOM '%' //
#define _C_ARY_B '[' // 代表array
#define _C_ARY_E ']'
#define _C_UNION_B '(' // 代表UNION
#define _C_UNION_E ')'
#define _C_STRUCT_B '{' // 代表结构体
#define _C_STRUCT_E '}'
#define _C_VECTOR '!' // 代表矢量类型
#define _C_CONST 'r' // 代表常量类型
例子1 Runtime
// 获取属性列表&&获取属性名称
unsigned int count;
objc_property_t *propertyList = class_copyPropertyList([self class], &count);
for (int i = 0; i < count ; i++) {
const char *propertyName = property_getName(propertyList[i]);
NSString *str = [NSString stringWithUTF8String:propertyName];
NSLog(@"property_getName==%@",str);
}
// 获取方法列表&&获取方法名称
Method *methodList = class_copyMethodList([self class], &count);
for (int i = 0; i < count; i++) {
Method method = methodList[i];
//获取方法的参数列表
int arguments = method_getNumberOfArguments(method);
NSLog(@"method_getNumberOfArguments===%d",arguments);
NSLog(@"method_getName===%@",NSStringFromSelector(method_getName(method)));
}
// 获取类成员变量列表&&获取成员变量名称
Ivar *ivarList = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivarList[i];
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
NSLog(@"ivar_getName===%@",ivarName);
}
// 获取类协议列表&&获取协议名称
__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);
for (unsigned int i = 0; i < count; i++) {
Protocol *protocol = protocolList[i];
NSString *protocolStr = [NSString stringWithUTF8String:protocol_getName(protocol)];
NSLog(@"protocol_getName===%@",protocolStr);
}
// 是不是元类
BOOL isMetaClass = class_isMetaClass(self.class);
NSLog(@"ViewController is the meta class? %d", isMetaClass);
// 是不是类对象
ViewController *obj = [ViewController new];
BOOL isClass = object_isClass(obj);
NSLog(@"ViewController is the class? %d", isClass);
// 获取类名称
const char *name = class_getName(self.class);
NSLog(@"class_getName===%@",[NSString stringWithCString:name encoding:NSUTF8StringEncoding]);
// 设置关联&&获取关联
static char *key = "key";
objc_setAssociatedObject(self, &key, @"hello world", OBJC_ASSOCIATION_COPY_NONATOMIC);
NSString *associated = objc_getAssociatedObject(self, &key);
NSLog(@"objc_getAssociatedObject===%@",associated);
/*----------------------Method Swizzling------------------------*/
// 获取实例方法
Method originalMethod = class_getInstanceMethod([self class], @selector(original:));
Method exchangeMethod = class_getInstanceMethod([self class], @selector(exchange:));
// 获取方法指针
IMP exchangeImp = method_getImplementation(exchangeMethod);
IMP originalImp = method_getImplementation(originalMethod);
// 获取描述方法的参数类型
const char *originalType = method_getTypeEncoding(originalMethod);
const char *exchangeType = method_getTypeEncoding(exchangeMethod);
// 添加方法
BOOL didAddMethod = class_addMethod([self class],
@selector(original:),
exchangeImp,
exchangeType);
if (didAddMethod) {
// 替换方法
class_replaceMethod([self class],
@selector(exchange:),
originalImp,
originalType);
}else{
// Method Swizzling
method_exchangeImplementations(exchangeMethod, originalMethod);
}
/*----------------------Method Swizzling------------------------*/
例子2 Runtime message
// 初始化 [[MsgSend1 alloc] init];
MsgSend1 *msg = ((MsgSend1 * (*)(id,SEL))objc_msgSend)((id)[MsgSend1 class], @selector(alloc));
msg = ((MsgSend1 * (*)(id,SEL))objc_msgSend)((id)msg, @selector(init));
// 发送无参无返回值消息
((void (*)(id,SEL))objc_msgSend)((id)msg, @selector(noArgumentsAndNoReturnValue));
// 发送有参数无返回值得消息
((void (*)(id,SEL,NSString *))objc_msgSend)((id)msg, @selector(hasArguments:),@"带参数但是无返回值");
// 带返回值不带参数消息
NSString *retValue = ((NSString * (*)(id,SEL))objc_msgSend)((id)msg,@selector(noArgumentsButReturnValue));
NSLog(@"%@",retValue);
// 带参数带返回值消息
int returnValue = ((int (*)(id,SEL,NSString *,int))objc_msgSend)((id)msg,@selector(hasValue1:Value2:),@"参数",999);
NSLog(@"return value is %d",returnValue);
// 动态添加方法再调用 其中i代表返回类型int,@代表参数,:代表SEL
class_addMethod(msg.class, NSSelectorFromString(@"cStyleFunc"), (IMP)cStyleFunc,"i@:");
returnValue = ((int (*)(id,SEL,const void *,const void *))objc_msgSend)((id)msg,NSSelectorFromString(@"cStyleFunc"),"one","two");
NSLog(@"return value is %d",returnValue);
// 带返回浮点值的消息
//objc_msgSend
//float returnFloatValue = ((float (*)(id,SEL))objc_msgSend)((id)msg,@selector(returnFloatType));
//objc_msgSend_fpret
float returnFloatValue = ((float (*)(id,SEL))objc_msgSend_fpret)((id)msg,@selector(returnFloatType));
NSLog(@"return float is %f",returnFloatValue);
// 带结构体返回值的消息
//objc_msgSend_stret
CGRect frame = ((CGRect (*)(id,SEL))objc_msgSend_stret)((id)self,@selector(returnTypeIsStruct));
NSLog(@"return frame is %@",NSStringFromCGRect(frame));