版本:iOS13.5
runtime.h
需要引入头文件#import
runtime其他方法通道
索引
- 获取已命名类的id。(ARC模式下不可用 )
objc_getFutureClass
- 创建一个类的实例,并在默认的malloc内存区域中为该类分配内存。
class_createInstance
- 在提供的特定位置创建类的实例。(ARC模式不可用)
objc_constructInstance
- 在不释放内存的情况下销毁类的实例,并删除该实例可能具有的所有关联引用。(ARC模式不可用)
objc_destructInstance
- 创建一个新的类和元类。
objc_allocateClassPair
- 注册并使用该类。
objc_registerClassPair
- 获取重复的类。
objc_duplicateClass
- 销毁一个类及其相关的元类。
objc_disposeClassPair
- 获取方法的选择器。
method_getName
- 返回方法的实现指针。
method_getImplementation
- 返回方法的描述参数和返回类型的字符串。
method_getTypeEncoding
- 返回方法接受的参数数量。
method_getNumberOfArguments
- 返回方法的描述返回类型的字符串。
method_copyReturnType
- 返回方法的描述单个参数类型的字符串。
method_copyArgumentType
- 获取方法的描述返回类型的字符串。
method_getReturnType
- 获取方法的描述单个参数类型的字符串。
method_getArgumentType
- 返回方法的描述结构体。
method_getDescription
- 为方法设置新的实现指针。
method_setImplementation
- 交换两种方法的实现指针。
method_exchangeImplementations
详解
- 获取已命名类的id。(ARC模式下不可用 )
Class _Nonnull objc_getFutureClass(const char * _Nonnull name) OBJC_ARC_UNAVAILABLE
警告:你不应该调用该函数
返回命名类的ID,或在加载时(如果加载)将用于该类的未初始化的类结构体。
- 创建一个类的实例,并在默认的malloc内存区域中为该类分配内存。
id _Nullable class_createInstance(Class _Nullable cls, size_t extraBytes)
extraBytes 要分配的额外字节数。除类中已定义的变量外,额外字节可用于存储其他实例变量。
id 返回该类的实例
例:
id instance = class_createInstance(object_getClass(self), 0);
- 在提供的特定位置创建类的实例。(ARC模式不可用)
id _Nullable objc_constructInstance(Class _Nullable cls, void * _Nullable bytes)
OBJC_ARC_UNAVAILABLE
bytes 实例的位置。需要指向对齐良好的零填充内存,且必须至少class_getInstanceSize
字节
- 在不释放内存的情况下销毁类的实例,并删除该实例可能具有的所有关联引用。(ARC模式不可用)
void * _Nullable objc_destructInstance(id _Nullable obj) OBJC_ARC_UNAVAILABLE
obj 类的实例,通过objc_constructInstance
创建
- 创建一个新的类和元类。
Class _Nullable objc_allocateClassPair(Class _Nullable superclass,
const char * _Nonnull name, size_t extraBytes)
要创建新类,请先调用
objc_allocateClassPair
,然后使用class_addMethod
和class_addIvar
之类的函数设置类的方法和属性,最后调用objc_registerClassPair
,就可以使用新类了。
其中实例方法和实例变量添加到类本身。类方法应添加到元类。
superclass 创建的类的父类,传nil表示创建新的根类。
name 新类的名字的字符串,该字符串将被复制。
extraBytes 在类和元类对象末尾为已索引的ivars分配的字节数。通常应为0。
Class 返回新类 若已有同名的类,则返回nil。
例子见objc_registerClassPair
- 注册并使用该类。
void objc_registerClassPair(Class _Nonnull cls)
cls 该类必须是通过objc_allocateClassPair
创建的
例:
Class Model = objc_allocateClassPair(objc_getClass("NSObject"), "Model", 0);
//添加变量
class_addIvar(Model, "adress", sizeof(NSString *), log2(sizeof(NSString *)), @encode(NSString *));
//添加方法
SEL getInfo = @selector(getInfo);
IMP getInfoImp = class_getMethodImplementation(Model, getInfo);
class_addMethod(Model, getInfo, getInfoImp, "v@:");
objc_registerClassPair(Model);
id model = class_createInstance(Model, 0);
NSLog(@"%@ %s %@", model,
ivar_getName(class_getInstanceVariable(Model, "adress")),
NSStringFromSelector(method_getName(class_getInstanceMethod(Model, getInfo))));
输出:
adress getInfo
- 获取重复的类。
Class _Nonnull objc_duplicateClass(Class _Nonnull original, const char * _Nonnull name,
size_t extraBytes)
由Foundation使用。
警告:你不应该调用该函数。
- 销毁一个类及其相关的元类。
void objc_disposeClassPair(Class _Nonnull cls)
如果存在此类或子类的实例,请不要调用。
cls 要销毁的类 它必须是使用objc_allocateClassPair
进行创建的。
- 获取方法的选择器。
SEL _Nonnull method_getName(Method _Nonnull m)
m 方法
通过class_getInstanceMethod
获取实例方法
通过class_getClassMethod
获取类方法
SEL 返回选择器 可通过sel_getName
获取选择器的名称
例子见method_getTypeEncoding
- 返回方法的实现指针。
IMP _Nonnull method_getImplementation(Method _Nonnull m)
例子见method_getTypeEncoding
- 返回方法的描述参数和返回类型的字符串。
const char * _Nullable method_getTypeEncoding(Method _Nonnull m)
例:
Method method1 = class_getInstanceMethod(object_getClass(self), @selector(getPhoneWithName:));
//获取方法的选择器
SEL method1Sel = method_getName(method1);
NSLog(@"%s", sel_getName(method1Sel));
//获取方法的实现指针
IMP method1IMP = method_getImplementation(method1);
//获取方法的返回类型与参数的描述字符串
const char *method1Char = method_getTypeEncoding(method1);
NSLog(@"%s", method1Char);
- (NSNumber *)getPhoneWithName:(NSString *)name {
NSLog(@"%@", name);
return @(13111111111);
}
输出:
getPhoneWithName:
@24@0:8@16
- 返回方法接受的参数数量。
unsigned int method_getNumberOfArguments(Method _Nonnull m)
例子见method_copyArgumentType
- 返回方法的描述返回类型的字符串。
char * _Nonnull method_copyReturnType(Method _Nonnull m)
你必须通过
free
释放字符串。
例子见method_copyArgumentType
- 返回方法的描述单个参数类型的字符串。
char * _Nullable method_copyArgumentType(Method _Nonnull m, unsigned int index)
你必须通过
free
释放字符串。
index 要查询的参数的索引 从2开始 前2个参数已被系统使用
char * 如果方法没有对应索引的参数,则返回NULL。
例:
Method method1 = class_getInstanceMethod(object_getClass(self), @selector(getPhoneWithName:));
unsigned int arguments = method_getNumberOfArguments(method1);
char *returnType = method_copyReturnType(method1);
//参数从第三个开始算
char *argumentType = method_copyArgumentType(method1, 2);
NSLog(@"%d %s %s", arguments, returnType, argumentType);
- (NSNumber *)getPhoneWithName:(NSString *)name {
NSLog(@"%@", name);
return @(13111111111);
}
输出:
3 @ @
method_getTypeEncoding例子输出的@24@0:8@16 @24表示返回参数 对应上面的第一个@
@0表示3个参数中的第一个 :8表示参数的第二个 这两个已经被系统使用
@16表示参数的第三个,也是自己定义的参数name,对应下面的第二个@
- 获取方法的描述返回类型的字符串。
void method_getReturnType(Method _Nonnull m, char * _Nonnull dst, size_t dst_len)
dst 存储描述的字符串 需要给dst通过malloc
分配内存
dst_len dst可以存储的最大字节数
例子见method_getDescription
- 获取方法的描述单个参数类型的字符串。
void method_getArgumentType(Method _Nonnull m, unsigned int index,
char * _Nullable dst, size_t dst_len)
index 要查询的参数的索引 从2开始 前2个参数已被系统使用
dst 存储描述的字符串 需要给dst通过malloc
分配内存
dst_len dst可以存储的最大字节数
例子见method_getDescription
- 返回方法的描述结构体。
struct objc_method_description * _Nonnull method_getDescription(Method _Nonnull m)
objc_method_description 返回的结构体
struct objc_method_description {
//方法的选择器
SEL _Nullable name;
//方法的参数类型
char * _Nullable types;
};
例:
char *returnType1 = malloc(10);
method_getReturnType(method1, returnType1, 10);
char *argumentType1 = malloc(10);
method_getArgumentType(method1, 2, argumentType1, 10);
NSLog(@"%s %s", returnType1, argumentType1);
free(returnType1);
free(argumentType1);
struct objc_method_description *des = method_getDescription(method1);
struct objc_method_description desInfo = des[0];
NSLog(@"%@ %s", NSStringFromSelector(desInfo.name), desInfo.types);
- (NSNumber *)getPhoneWithName:(NSString *)name {
NSLog(@"%@", name);
return @(13111111111);
}
输出:
@ @
getPhoneWithName: @24@0:8@16
- 为方法设置新的实现指针。
IMP _Nonnull method_setImplementation(Method _Nonnull m, IMP _Nonnull imp)
详细说明见方法
class_addMethod
imp 新的方法实现指针
IMP 返回之前的指针
例子见method_exchangeImplementations
- 交换两种方法的实现指针。
void method_exchangeImplementations(Method _Nonnull m1, Method _Nonnull m2)
效果如同下面代码
IMP imp1 = method_getImplementation(m1);
IMP imp2 = method_getImplementation(m2);
method_setImplementation(m1, imp2);
method_setImplementation(m2, imp1);
例:
Method a = class_getInstanceMethod(object_getClass(self), NSSelectorFromString(@"a"));
Method b = class_getInstanceMethod(object_getClass(self), NSSelectorFromString(@"b"));
[self a];
[self b];
method_exchangeImplementations(a, b);
[self a];
[self b];
- (void)a {
NSLog(@"aaa");
}
- (void)b {
NSLog(@"bbb");
}
输出:
aaa
bbb
bbb
aaa