版本:iOS13.5
runtime.h
需要引入头文件#import
runtime其他方法通道
索引
- 返回实例变量的名称。
ivar_getName
- 返回实例变量的类型字符串。
ivar_getTypeEncoding
- 返回实例变量的内存偏移量。
ivar_getOffset
- 返回属性的名字。
property_getName
- 返回属性的attribute字符串。
property_getAttributes
- 返回属性的attribute数组。
property_copyAttributeList
- 通过attribute名返回属性的attribute的值。
property_copyAttributeValue
- 返回对应名字的协议。
objc_getProtocol
- 返回运行时已知的所有协议的数组。
objc_copyProtocolList
- 判断协议proto是否符合协议other。
protocol_conformsToProtocol
- 判断协议proto和协议other是否相同。
protocol_isEqual
- 返回协议的名字。
protocol_getName
- 返回协议proto的方法aSel的方法描述结构体。
protocol_getMethodDescription
- 返回协议proto的方法描述结构体数组。
protocol_copyMethodDescriptionList
- 返回协议proto的对应名字的属性。
protocol_getProperty
- 返回协议proto的必需实例属性的数组。
protocol_copyPropertyList
- 返回协议proto的属性数组。
protocol_copyPropertyList2
- 返回协议proto符合的协议数组。
protocol_copyProtocolList
- 创建一个新的协议实例。
objc_allocateProtocol
- 注册一个新的协议。
objc_registerProtocol
- 向正在构建的协议添加方法。
protocol_addMethodDescription
- 向正在构建的协议添加要符合的协议。
protocol_addProtocol
- 向正在构建的协议添加属性。
protocol_addProperty
详解
- 返回实例变量的名称。
const char * _Nullable ivar_getName(Ivar _Nonnull v)
例子见ivar_getOffset
- 返回实例变量的类型字符串。
const char * _Nullable ivar_getTypeEncoding(Ivar _Nonnull v)
例子见ivar_getOffset
- 返回实例变量的内存偏移量。
ptrdiff_t ivar_getOffset(Ivar _Nonnull v)
内存偏移量,即该成员变量对于该对象的内存地址偏移了多少。
对于类型为id或其他对象类型的实例变量,请调用object_getIvar
和object_setIvar
,而不要使用此偏移量直接访问实例变量数据。
例:
Ivar title0Ivar = class_getInstanceVariable(self.class, "_title0");
const char *title0Name = ivar_getName(title0Ivar);
const char *title0Type = ivar_getTypeEncoding(title0Ivar);
ptrdiff_t title0Offset = ivar_getOffset(title0Ivar);
NSLog(@"%s, %s, %ld", title0Name, title0Type, title0Offset);
输出:
_title0, @"NSString", 864
- 返回属性的名字。
const char * _Nonnull property_getName(objc_property_t _Nonnull property)
例子见property_copyAttributeValue
- 返回属性的attribute字符串。
const char * _Nullable property_getAttributes(objc_property_t _Nonnull property)
关于attribute,详见runtime中的
class_addProperty
方法
例子见property_copyAttributeValue
- 返回属性的attribute数组。
objc_property_attribute_t * property_copyAttributeList(objc_property_t _Nonnull property,
unsigned int * _Nullable outCount)
该数组必须由调用方调用
free
释放。
outCount 指针,保存数组元素的数量。
例子见property_copyAttributeValue
- 通过attribute名返回属性的attribute的值。
char * _Nullable property_copyAttributeValue(objc_property_t _Nonnull property,
const char * _Nonnull attributeName)
attributeName 为下面的name
char * 返回的即为下面的value的copy
typedef struct {
//attribute名
const char * _Nonnull name;
//attribute值
const char * _Nonnull value;
} objc_property_attribute_t;
例:
objc_property_t title0Property = class_getProperty(object_getClass(self), "title0");
const char *title0PropertyName = property_getName(title0Property);
const char *title0PropertyAttribute = property_getAttributes(title0Property);
NSLog(@"%s, %s",title0PropertyName, title0PropertyAttribute);
unsigned int title0PropertyCount = 0;
objc_property_attribute_t *title0PropertyAttributes = property_copyAttributeList(title0Property, &title0PropertyCount);
for (NSInteger i = 0; i < title0PropertyCount; i++) {
objc_property_attribute_t attribute = title0PropertyAttributes[i];
char *value = property_copyAttributeValue(title0Property, attribute.name);
NSLog(@"%s, %s, %s", attribute.name, attribute.value, value);
}
输出:
title0, T@"NSString",&,N,V_title0
T, @"NSString", @"NSString"
&, ,
N, ,
V, _title0, _title0
- 返回对应名字的协议。
Protocol * _Nullable objc_getProtocol(const char * _Nonnull name)
若找不到名为name的协议,则返回NULL
例子见protocol_getName
- 返回运行时已知的所有协议的数组。
Protocol * __unsafe_unretained _Nonnull * _Nullable
objc_copyProtocolList(unsigned int * _Nullable outCount)
您必须使用
free
释放数组
outCount 指针,保存数组元素的数量。
例子见protocol_getName
- 判断协议proto是否符合协议other。
BOOL protocol_conformsToProtocol(Protocol * _Nullable proto, Protocol * _Nullable other)
BOOL 若符合,返回YES,否则返回NO。
例子见protocol_getName
- 判断协议proto和协议other是否相同。
BOOL protocol_isEqual(Protocol * _Nullable proto, Protocol * _Nullable other)
BOOL 若相同,返回YES,否则返回NO。
例子见protocol_getName
- 返回协议的名字。
const char * _Nonnull protocol_getName(Protocol * _Nonnull proto)
例:
Protocol *runtimeProtocol = objc_getProtocol("runtimeProtocol");
const char *runtimeProtocolName = protocol_getName(runtimeProtocol);
unsigned int allProtocolsCount = 0;
Protocol * __unsafe_unretained _Nonnull * _Nullable allProtocols = objc_copyProtocolList(&allProtocolsCount);
NSLog(@"%s %d", runtimeProtocolName, allProtocolsCount);
Protocol *nsobjectProtocol = objc_getProtocol("NSObject");
BOOL conform = protocol_conformsToProtocol(runtimeProtocol, nsobjectProtocol);
BOOL equal = protocol_isEqual(runtimeProtocol, nsobjectProtocol);
NSLog(@"%@ %@", @(conform), @(equal));
@protocol runtimeProtocol
@optional
- (void)test;
@end
输出:
runtimeProtocol 3937
1 0
- 返回协议proto的方法aSel的方法描述结构体。
struct objc_method_description
protocol_getMethodDescription(Protocol * _Nonnull proto, SEL _Nonnull aSel,
BOOL isRequiredMethod, BOOL isInstanceMethod)
aSel 协议中方法的选择器
isRequiredMethod 指示方法是否为必需方法
isInstanceMethod 指示方法是否为实例方法
objc_method_description 若协议不包含该方法,则返回{NULL, NULL}。
例子见protocol_copyMethodDescriptionList
- 返回协议proto的方法描述结构体数组。
objc_method_description * _Nullable
protocol_copyMethodDescriptionList(Protocol * _Nonnull proto,
BOOL isRequiredMethod, BOOL isInstanceMethod,unsigned int * _Nullable outCount)
不包括该协议符合的其他协议中的方法。
你必须调用free
释放该数组。
outCount 指针,保存数组元素的数量。
例:
Protocol *runtimeProtocol = objc_getProtocol("runtimeProtocol");
struct objc_method_description testDescription = protocol_getMethodDescription(runtimeProtocol, NSSelectorFromString(@"test"), NO, YES);
NSLog(@"%@ %s", NSStringFromSelector(testDescription.name), testDescription.types);
unsigned int descriptionListCount = 0;
struct objc_method_description *descriptionList = protocol_copyMethodDescriptionList(runtimeProtocol, NO, YES, &descriptionListCount);
NSLog(@"%d", descriptionListCount);
for (NSInteger i = 0; i < descriptionListCount; i++) {
struct objc_method_description description = descriptionList[i];
NSLog(@"%@ %s", NSStringFromSelector(description.name), description.types);
}
@protocol runtimeProtocol
@optional
- (void)test;
- (void)test1;
@end
输出:
test v16@0:8
2
test1 v16@0:8
test v16@0:8
- 返回协议proto的对应名字的属性。
objc_property_t _Nullable
protocol_getProperty(Protocol * _Nonnull proto,
const char * _Nonnull name,
BOOL isRequiredProperty, BOOL isInstanceProperty)
name 属性的名字
isRequiredProperty 是否为必须属性
isInstanceProperty 是否为实例属性
objc_property_t 若没有符合的属性,则返回NULL。
例子见protocol_copyPropertyList2
- 返回协议proto的必需实例属性的数组。
objc_property_t _Nonnull * _Nullable
protocol_copyPropertyList(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount)
等效于
protocol_copyPropertyList2(proto, outCount, YES, YES)
您必须使用free
释放数组。
outCount 指针,保存数组元素的数量。
例子见protocol_copyPropertyList2
- 返回协议proto的属性数组。
objc_property_t _Nonnull * _Nullable
protocol_copyPropertyList2(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount,
BOOL isRequiredProperty, BOOL isInstanceProperty)
您必须使用
free
释放数组。
outCount 指针,保存数组元素的数量。
isRequiredProperty 是否为必须属性
isInstanceProperty 是否为实例属性
objc_property_t * 若协议没有对应的属性,则返回NULL。
例:
Protocol *runtimeProtocol = objc_getProtocol("runtimeProtocol");
objc_property_t phoneNum = protocol_getProperty(runtimeProtocol, "phoneNum", YES, YES);
NSLog(@"%s", property_getName(phoneNum));
unsigned int propertyListCount = 0;
(void)protocol_copyPropertyList(runtimeProtocol, &propertyListCount);
NSLog(@"%d", propertyListCount);
objc_property_t *propertyList = protocol_copyPropertyList2(runtimeProtocol, &propertyListCount, YES, YES);
NSLog(@"%d", propertyListCount);
for (NSInteger i = 0; i < propertyListCount; i++) {
objc_property_t property = propertyList[i];
NSLog(@"%s", property_getName(property));
}
free(propertyList);
@protocol runtimeProtocol
@optional
- (void)test;
- (void)test1;
@property (nonatomic, strong) NSString *phoneNum;
@property (nonatomic, strong) NSString *name;
@end
输出:
phoneNum
2
2
phoneNum
name
- 返回协议proto符合的协议数组。
Protocol * __unsafe_unretained _Nonnull * _Nullable
protocol_copyProtocolList(Protocol * _Nonnull proto,
unsigned int * _Nullable outCount)
您必须使用
free
释放数组。
outCount 指针,保存数组元素的数量。
例:
unsigned int copyProtocolListCount = 0;
Protocol * __unsafe_unretained _Nonnull *copyProtocolList = protocol_copyProtocolList(runtimeProtocol, ©ProtocolListCount);
NSLog(@"%d", copyProtocolListCount);
for (NSInteger i = 0; i < copyProtocolListCount; i++) {
Protocol * __unsafe_unretained _Nonnull property = copyProtocolList[i];
const char *name = protocol_getName(property);
NSLog(@"%s", name);
}
free(copyProtocolList);
@protocol runtimeProtocol
@end
输出:
1
NSObject
- 创建一个新的协议实例。
Protocol * _Nullable objc_allocateProtocol(const char * _Nonnull name)
新的协议需要调用
objc_registerProtocol
注册后才能使用
name 协议的名字
Protocol * 返回成功的Protocol实例,如果已经存在相同名称的协议,则返回nil。
例子见protocol_addProperty
- 注册一个新的协议。
void objc_registerProtocol(Protocol * _Nonnull proto)
proto 通过objc_allocateProtocol
创建
例子见protocol_addProperty
- 向正在构建的协议添加方法。
void protocol_addMethodDescription(Protocol * _Nonnull proto, SEL _Nonnull name,
const char * _Nullable types,BOOL isRequiredMethod, BOOL isInstanceMethod)
正在构建中,即
objc_allocateProtocol
与objc_registerProtocol
之间的状态
proto 正在构建中的协议
name 方法的选择器
types 方法的参数类型字符 详情可见runtime的class_addMethod
方法
isRequiredMethod 是否为必须方法
isInstanceMethod 是否为实例方法
例子见protocol_addProperty
- 向正在构建的协议添加要符合的协议。
void protocol_addProtocol(Protocol * _Nonnull proto, Protocol * _Nonnull addition)
正在构建中,即
objc_allocateProtocol
与objc_registerProtocol
之间的状态
proto 正在构建的协议。
addition proto要符合的协议,必须已经构建。
例子见protocol_addProperty
- 向正在构建的协议添加属性。
void protocol_addProperty(Protocol * _Nonnull proto, const char * _Nonnull name,
const objc_property_attribute_t * _Nullable attributes,
unsigned int attributeCount,
BOOL isRequiredProperty, BOOL isInstanceProperty)
正在构建中,即
objc_allocateProtocol
与objc_registerProtocol
之间的状态
name 属性的名字
attributes 属性的attributes 详见runtime的class_addProperty
方法
attributeCount attributes元素的个数
isRequiredProperty 是否为必须属性
isInstanceProperty 是否为实例属性 YES是该属性唯一允许的情况,若将此属性设置为NO则不会将该属性添加到协议。
例:
Protocol *testProtocol = objc_allocateProtocol("testProtocol");
protocol_addMethodDescription(testProtocol, NSSelectorFromString(@"getName"), "v@:", NO, YES);
protocol_addProtocol(testProtocol, runtimeProtocol);
objc_property_attribute_t adressAttribute0 = {"T", [[NSString stringWithFormat:@"@\"%@\"", @"NSString"] UTF8String]};//属性的类型 T表示type
objc_property_attribute_t adressAttribute1 = {"&", ""};//&表示strong C表示copy N表示nonatomic 其他的请自行查看
objc_property_attribute_t adressAttribute2 = {"N", ""};
objc_property_attribute_t adressAttribute3 = {"V", [[NSString stringWithFormat:@"_%@", @"adress"] UTF8String]};//属性的名字
objc_property_attribute_t adressAttrs[] = {adressAttribute0, adressAttribute1, adressAttribute2, adressAttribute3};
protocol_addProperty(testProtocol, "adress", adressAttrs, 4, YES, YES);
objc_registerProtocol(testProtocol);
相当于创建了下面的协议
@protocol testProtocol
- (void)getName;
@property (nonatomic, strong) NSString *adress;
@end