Objective-C Runtime
Runtime
Working with Classes
- class_getName
返回类的名字
const char * name=class_getName([Person class]);
NSLog(@"name=%s",name);
NSString *userName=[NSString stringWithUTF8String:name];
NSLog(@"userName=%@",userName);
- class_getSuperclass
返回父类的类的类型(class)
Class aclass = class_getSuperclass([Student class]);
const char * name = class_getName(aclass);
NSLog(@"name=%s",name);
NSString *userName=[NSString stringWithUTF8String:name];
NSLog(@"userName=%@",userName);
- class_isMetaClass
返回该类是否是元类
BOOL isMeta = class_isMetaClass([NSObject class]);
- class_getInstanceSize
返回该类实例的大小
size_t size = class_getInstanceSize([Person class]);
NSLog(@"%zu",size);
- class_getInstanceVariable
返回实例变量的Ivar
Ivar ivar = class_getInstanceVariable([Person class],"_name");
const char * ivar_name=ivar_getName(ivar);
NSLog(@"ivar_name = %@",[NSString stringWithUTF8String:ivar_name]);
- class_addIvar
给类添加成员变量
- 该方法不能给已经存在的类添加成员变量
- 该方法只能在 objc_allocateClassPair方法之后,objc_registerClassPair这个方法之前调用
BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types);
Class People = objc_allocateClassPair([NSObject class], "People", 0);
class_addIvar(People, "_name", sizeof(NSString *), 0, @encode(NSString *));
class_addIvar(People, "_age", sizeof(NSNumber *), 0, @encode(NSNumber *));
objc_registerClassPair(People);
- class_addProperty
给类添加属性
BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
objc_property_attribute_t attribute1 = {"T", @encode(NSString *)};
objc_property_attribute_t attribute2 = {"N", ""};
objc_property_attribute_t attribute3 = {"&", ""};
objc_property_attribute_t attribute[] = {attribute1, attribute2, attribute3};
class_addProperty([HCBase class], "sb", attribute, 3);
- class_addMethod
给已经存在的类添加实例方法
_aperson =[[Person alloc]init];
BOOL sucess = class_addMethod([Person class],(NSSelectorFromString(@"methodName")),class_getMethodImplementation([self class], @selector(printtext:)), "v@:@");
if(sucess){
[_aperson performSelector:(NSSelectorFromString(@"methodName")) withObject:@"hahahhahah" afterDelay:0];
}
- class_addProtocol
给一个已有的类添加协议
BOOL class_addProtocol(Class cls, Protocol *protocol);
BOOL sucess = class_addProtocol([Person class],_test);
- class_copyIvarList
获取一个类的成员变量列表的一个拷贝
Ivar _Nonnull * class_copyIvarList(Class cls, unsigned int *outCount);
unsigned int count;
Ivar * ivars = class_copyIvarList([Person class], &count);
for (int i=0; i<count; i++) {
NSLog(@"-----%@",[NSString stringWithUTF8String:ivar_getName(ivars[i])]);
}
free(ivars);
- outcount为成员变量的个数
- 只会显示当前类的成员变量,不包括父类的任何成员变量
- 你必须使用free()方法释放ivars数组
- class_getIvarLayout
获取类所有的strong修饰符数组
const uint8_t * class_getIvarLayout(Class cls);
const uint8_t *array_s = class_getIvarLayout([Person class]);
int i = 0;
uint8_t value_s = array_s[i];
while (value_s != 0x0) {
printf("\\x%02x\n", value_s);
value_s = array_s[++i];
}
- class_setIvarLayout
设置Ivar 属性修饰符
void class_setIvarLayout(Class cls, const uint8_t *layout);
- class_getWeakIvarLayout
获取类所有的weak修饰符数组
const uint8_t * class_getWeakIvarLayout(Class cls);
const uint8_t *array_s1 = class_getWeakIvarLayout([Person class]);
int j = 0;
uint8_t value_s1 = array_s1[j];
while (value_s1 != 0x0) {
printf("\\x%02x\n", value_s1);
value_s1 = array_s1[++j];
}
- class_setWeakIvarLayout
设置Ivar weak修饰符
void class_setWeakIvarLayout(Class cls, const uint8_t *layout);
- class_getProperty
获取指定属性
objc_property_t class_getProperty(Class cls, const char *name);
objc_property_t propert_t = class_getProperty([Person class],"name");
const char * properName = property_getName(propert_t);
NSLog(@"--%@",[NSString stringWithUTF8String:properName]);
- class_copyPropertyList
获取一个类的属性列表的一个拷贝
objc_property_t _Nonnull * class_copyPropertyList(Class cls, unsigned int *outCount);
unsigned int count;
objc_property_t *array = class_copyPropertyList([Person class], &count);
for (int i=0; i<count; i++) {
const char * name = property_getName(array[i]);
NSLog(@"---%@",[NSString stringWithUTF8String:name]);
}
- class_getInstanceMethod
获取类中的指定实例的 Method
Method class_getInstanceMethod(Class cls, SEL name);
Method method = class_getInstanceMethod([Person class], @selector(printName));
NSLog(@"---%@",[NSString stringWithUTF8String:(method_getName(method))]);
- class_getClassMethod
获取类中指定的类的Method
Method class_getClassMethod(Class cls, SEL name);
- class_copyMethodList
获取当前类的所有实例方法的拷贝
Method _Nonnull * class_copyMethodList(Class cls, unsigned int *outCount);
unsigned int count;
Method *methods = class_copyMethodList([Person class], &count);
for (int i = 0; i < count; i++) {
const char *methodName =sel_getName((method_getName(methods[i])));
NSLog(@"---methodname=%@",[NSString stringWithUTF8String:methodName]);
}
- class_replaceMethod
替换类中方法的实现地址
IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
Method originalMethod = class_getInstanceMethod([Person class], @selector(printName));
Method swizzledMethod = class_getInstanceMethod([Person class], @selector(printAge));
class_replaceMethod([Person class],
@selector(printAge),
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
Person *person = [[Person alloc]init];
[person printAge];
- 返回替换后旧的IMP
- types类型可以使用该方法获取:method_getTypeEncoding()
- 如果要替换的方法不存在,首先需要使用class_addMethod添加方法,然后在去替换
- class_getMethodImplementation
获取类中指定方法的方法指针
IMP class_getMethodImplementation(Class cls, SEL name);
IMP methodImp = class_getMethodImplementation([Person class], @selector(printName));
NSLog(@"%ld",(long)methodImp);
- class_respondsToSelector
是否类的实例能够响应该方法
BOOL class_respondsToSelector(Class cls, SEL sel);
可使用下列方法替换:
- respondsToSelector:
- instancesRespondToSelector:
- class_replaceProperty
替换类中的一个属性
void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
- (void)class_replaceProperty:(Class)class class_name:(const char *)class_name replace_name:(const char *)replace_name{
objc_property_attribute_t type = { "T", "@\"NSString\"" };
objc_property_attribute_t ownership = { "C", "" }; // C = copy
objc_property_attribute_t backingivar = { "V", replace_name };
objc_property_attribute_t attrs[] = { type, ownership, backingivar };
class_replaceProperty(class, class_name, attrs, 3);
}
- class_conformsToProtocol
判断该类是否遵循协议
BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
可用NSObject里边的conformsToProtocol:替换
Adding Classes
- objc_allocateClassPair
创建一个新的类和元类
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
extraBytes参数通常为0
- 实例变量及实例方法添加到类中
- 类方法添加至元类中
- objc_disposeClassPair
销毁一个类及它的的元类
void objc_disposeClassPair(Class cls);
当该类的实例及子类存在时,不能调用该方法
- objc_registerClassPair
注册一个类
void objc_registerClassPair(Class cls);
Instantiating Classes
- class_createInstance
创建一个类的实例,且默认分配内存空间
id class_createInstance(Class cls, size_t extraBytes);
- objc_constructInstance
幢一个类的实例,且分配实例的字节大小
id objc_constructInstance(Class cls, void *bytes);
- objc_destructInstance
销毁了一个类的实例没有释放内存并删除任何相关的引用
void * objc_destructInstance(id obj);
Working with Instances
- object_copy
返回一个对象的拷贝
id object_copy(id obj, size_t size);
- object_dispose
释放一个对象的内存
id object_dispose(id obj);
- object_setInstanceVariable
修改一个类的实例的变量值
Ivar object_setInstanceVariable(id obj, const char *name, void *value)
Person *person =[[Person alloc]init];
NSString * string = @"xiao hong";
Ivar ivar = object_setInstanceVariable(person,"_name",&string);
[person printName];
ARC环境下不可用
- object_getInstanceVariable
获取一个实例的变量值
Ivar object_getInstanceVariable(id obj, const char *name, void * _Nullable *outValue);
Person *person =[[Person alloc]init];
NSString *name;
object_getInstanceVariable(person,"_name",&name);
NSLog(@"name = %@",name);
ARC环境下不可用
- object_getClassName
获取一个对象的类名
const char * object_getClassName(id obj);
- object_getClass
返回一个对象的Class
Class object_getClass(id obj);
Person *person =[[Person alloc]init];
Class aclass = object_getClass(person);
NSLog(@"---aclass = %@",[NSString stringWithUTF8String:(class_getName(aclass))]);
- object_setClass
修改实例的类 返回之前的类的Class
Class object_setClass(id obj, Class cls);
Person *person =[[Person alloc]init];
Class aclass = object_setClass(person, [Student class]);
NSLog(@"---aclass = %@",[NSString stringWithUTF8String:(class_getName(aclass))]);
NSLog(@"person = %@",[NSString stringWithUTF8String:object_getClassName(person)]);
Working with Instance Variables
- ivar_getName
返回变量的名字
const char * ivar_getName(Ivar v);
- ivar_getTypeEncoding
返回string类型的变量类型
const char * ivar_getTypeEncoding(Ivar v);
- ivar_getOffset
返回变量的偏移量
ptrdiff_t ivar_getOffset(Ivar v);
Associative References
- objc_setAssociatedObject
给一个对象添加协议键值
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
objc_setAssociatedObject(self,&flashColorKey, flashColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
给分类添加协议属性时用到
- objc_getAssociatedObject
获取对象的协议值
id objc_getAssociatedObject(id object, const void *key);
给分类添加协议属性时用到
- objc_removeAssociatedObjects
移除对象的所有协议
void objc_removeAssociatedObjects(id object);
一般通过将value设置成nil来移除协议关系,如果用该方法会影响别的协议
Sending Messages
- objc_msgSend
id objc_msgSend(id self, SEL op, ...);
Person *person =[[Person alloc]init];
[person printName];
((void (*) (id, SEL)) objc_msgSend)(person, sel_registerName("printName"));
NSLog(@"---------%@",[person getPrintName:@"yangguoqiang"]);
NSString *name=((NSString * (*) (id, SEL,NSString *)) objc_msgSend)(person, sel_registerName("getPrintName:"),@"yangguoqiang");
NSLog(@"---------%@",name);
dog *adog = [person getDogWithAge:10 andLevel:1];
NSLog(@"---%@",[NSString stringWithUTF8String:object_getClassName(adog)]);
dog *twoDog = ((dog * (*) (id, SEL,NSInteger,NSInteger)) objc_msgSend)(person, sel_registerName("getDogWithAge:andLevel:"),10,1);
NSLog(@"---%@",[NSString stringWithUTF8String:object_getClassName(twoDog)]);
Working with Methods
- method_invoke
方法调用
id method_invoke(id receiver, Method m, ...);
Person *person =[[Person alloc]init];
[person printName];
Method method = class_getInstanceMethod([Person class], @selector(printName));
method_invoke(person,method);
- method_invoke_stret
方法调用返回一个结构体
void method_invoke_stret(id receiver, Method m, ...);
- method_getName
通过一个Method类型返回SEL类型
SEL method_getName(Method m);
Person *person =[[Person alloc]init];
[person printName];
Method method = class_getInstanceMethod([Person class], @selector(printName));
SEL seletor = method_getName(method);
NSLog(@"----%@",[NSString stringWithUTF8String:sel_getName(seletor)]);
- method_getImplementation
通过Method对象获取方法的IMP地址
IMP method_getImplementation(Method m);
- method_getTypeEncoding
通过Method的对象返回一个字符串,描述方法的参数及返回值
const char * method_getTypeEncoding(Method m);
Method method = class_getInstanceMethod([Person class], @selector(printName));
NSLog(@"----%@",[NSString stringWithUTF8String:method_getTypeEncoding(method)]);
- method_copyReturnType
通过Method的对象拷贝返回值的字符串 要使用free()方法释放
char * method_copyReturnType(Method m);
Method method = class_getInstanceMethod([Person class], @selector(getPrintName:));
NSLog(@"----%@",[NSString stringWithUTF8String:method_copyReturnType(method)]);
- method_copyArgumentType
按index返回字符串参数的类型 要使用free()方法释放
char * method_copyArgumentType(Method m, unsigned int index);
Method method = class_getInstanceMethod([Person class], @selector(getPrintName:));
NSLog(@"----%@",[NSString stringWithUTF8String:method_copyArgumentType(method,0)]);
- method_getNumberOfArguments
返回参数的个数
unsigned int method_getNumberOfArguments(Method m);
- method_setImplementation
给方法设置新的实现地址 返回旧的方法地址
IMP method_setImplementation(Method m, IMP imp);
- method_exchangeImplementations
交互两个方法的实现地址
void method_exchangeImplementations(Method m1, Method m2);
Person *person =[[Person alloc]init];
[person printName];
Method method1 = class_getInstanceMethod([Person class], @selector(printName));
Method method2 = class_getInstanceMethod([Person class], @selector(printAge));
method_exchangeImplementations(method1,method2);
[person printName];
Working with Libraries
- objc_copyImageNames
获取所有的Objective-C 动态库及静态库名称的字符串数组
const char * _Nonnull * objc_copyImageNames(unsigned int *outCount);
unsigned int count;
const char ** names = objc_copyImageNames(&count);
for (int i= 0; i<count; i++) {
NSLog(@"-----%@",[NSString stringWithUTF8String:names[i]]);
}
- class_getImageName
返回一个字符串路径,显示该类属于哪个库
const char * class_getImageName(Class cls);
const char * name = class_getImageName([Person class]);
NSLog(@"-----%@",[NSString stringWithUTF8String:name]);
- objc_copyClassNamesForImage
获取指点库中所有类的字符数组名
const char * _Nonnull * objc_copyClassNamesForImage(const char *image, unsigned int *outCount);
Working with Selectors
- sel_getName
获取SEL类型方法的字符串名称
const char * sel_getName(SEL sel);
- sel_registerName
在runtime系统中注册方法
SEL sel_registerName(const char *str);
- sel_getUid
在runtime系统中注册方法
SEL sel_getUid(const char *str);
- sel_isEqual
判断两个方法是不是相等
BOOL sel_isEqual(SEL lhs, SEL rhs);
Working with Protocols
- objc_getProtocol
Returns a specified protocol. - objc_copyProtocolList
Returns an array of all the protocols known to the runtime. - objc_allocateProtocol
Creates a new protocol instance. - objc_registerProtocol
Registers a newly created protocol with the Objective-C runtime. - protocol_addMethodDescription
Adds a method to a protocol. - protocol_addProtocol
Adds a registered protocol to another protocol that is under construction.
Working with Properties
- property_getName
返回属性的字符名称
const char * property_getName(objc_property_t property);
- property_getAttributes
返回属性的字符
Returns the attribute string of a property.
- property_copyAttributeValue
Returns the value of a property attribute given the attribute name.
char * property_copyAttributeValue(objc_property_t property, const char *attributeName);