Objective-C Runtime
Runtime
Working with Classes
- class_getName
返回類(lèi)的名字
const char * name=class_getName([Person class]);
NSLog(@"name=%s",name);
NSString *userName=[NSString stringWithUTF8String:name];
NSLog(@"userName=%@",userName);
- class_getSuperclass
返回父類(lèi)的類(lèi)的類(lèi)型(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
返回該類(lèi)是否是元類(lèi)
BOOL isMeta = class_isMetaClass([NSObject class]);
- class_getInstanceSize
返回該類(lèi)實(shí)例的大小
size_t size = class_getInstanceSize([Person class]);
NSLog(@"%zu",size);
- class_getInstanceVariable
返回實(shí)例變量的Ivar
Ivar ivar = class_getInstanceVariable([Person class],"_name");
const char * ivar_name=ivar_getName(ivar);
NSLog(@"ivar_name = %@",[NSString stringWithUTF8String:ivar_name]);
- class_addIvar
給類(lèi)添加成員變量
- 該方法不能給已經(jīng)存在的類(lèi)添加成員變量
- 該方法只能在 objc_allocateClassPair方法之后,objc_registerClassPair這個(gè)方法之前調(diào)用
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
給類(lèi)添加屬性
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
給已經(jīng)存在的類(lèi)添加實(shí)例方法
_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
給一個(gè)已有的類(lèi)添加協(xié)議
BOOL class_addProtocol(Class cls, Protocol *protocol);
BOOL sucess = class_addProtocol([Person class],_test);
- class_copyIvarList
獲取一個(gè)類(lèi)的成員變量列表的一個(gè)拷貝
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為成員變量的個(gè)數(shù)
- 只會(huì)顯示當(dāng)前類(lèi)的成員變量,不包括父類(lèi)的任何成員變量
- 你必須使用free()方法釋放ivars數(shù)組
- class_getIvarLayout
獲取類(lèi)所有的strong修飾符數(shù)組
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
設(shè)置Ivar 屬性修飾符
void class_setIvarLayout(Class cls, const uint8_t *layout);
- class_getWeakIvarLayout
獲取類(lèi)所有的weak修飾符數(shù)組
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
設(shè)置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
獲取一個(gè)類(lèi)的屬性列表的一個(gè)拷貝
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
獲取類(lèi)中的指定實(shí)例的 Method
Method class_getInstanceMethod(Class cls, SEL name);
Method method = class_getInstanceMethod([Person class], @selector(printName));
NSLog(@"---%@",[NSString stringWithUTF8String:(method_getName(method))]);
- class_getClassMethod
獲取類(lèi)中指定的類(lèi)的Method
Method class_getClassMethod(Class cls, SEL name);
- class_copyMethodList
獲取當(dāng)前類(lèi)的所有實(shí)例方法的拷貝
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
替換類(lèi)中方法的實(shí)現(xiàn)地址
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類(lèi)型可以使用該方法獲取:method_getTypeEncoding()
- 如果要替換的方法不存在,首先需要使用class_addMethod添加方法,然后在去替換
- class_getMethodImplementation
獲取類(lèi)中指定方法的方法指針
IMP class_getMethodImplementation(Class cls, SEL name);
IMP methodImp = class_getMethodImplementation([Person class], @selector(printName));
NSLog(@"%ld",(long)methodImp);
- class_respondsToSelector
是否類(lèi)的實(shí)例能夠響應(yīng)該方法
BOOL class_respondsToSelector(Class cls, SEL sel);
可使用下列方法替換:
- respondsToSelector:
- instancesRespondToSelector:
- class_replaceProperty
替換類(lèi)中的一個(gè)屬性
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
判斷該類(lèi)是否遵循協(xié)議
BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
可用NSObject里邊的conformsToProtocol:替換
Adding Classes
- objc_allocateClassPair
創(chuàng)建一個(gè)新的類(lèi)和元類(lèi)
Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
extraBytes參數(shù)通常為0
- 實(shí)例變量及實(shí)例方法添加到類(lèi)中
- 類(lèi)方法添加至元類(lèi)中
- objc_disposeClassPair
銷(xiāo)毀一個(gè)類(lèi)及它的的元類(lèi)
void objc_disposeClassPair(Class cls);
當(dāng)該類(lèi)的實(shí)例及子類(lèi)存在時(shí),不能調(diào)用該方法
- objc_registerClassPair
注冊(cè)一個(gè)類(lèi)
void objc_registerClassPair(Class cls);
Instantiating Classes
- class_createInstance
創(chuàng)建一個(gè)類(lèi)的實(shí)例,且默認(rèn)分配內(nèi)存空間
id class_createInstance(Class cls, size_t extraBytes);
- objc_constructInstance
幢一個(gè)類(lèi)的實(shí)例,且分配實(shí)例的字節(jié)大小
id objc_constructInstance(Class cls, void *bytes);
- objc_destructInstance
銷(xiāo)毀了一個(gè)類(lèi)的實(shí)例沒(méi)有釋放內(nèi)存并刪除任何相關(guān)的引用
void * objc_destructInstance(id obj);
Working with Instances
- object_copy
返回一個(gè)對(duì)象的拷貝
id object_copy(id obj, size_t size);
- object_dispose
釋放一個(gè)對(duì)象的內(nèi)存
id object_dispose(id obj);
- object_setInstanceVariable
修改一個(gè)類(lèi)的實(shí)例的變量值
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環(huán)境下不可用
- object_getInstanceVariable
獲取一個(gè)實(shí)例的變量值
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環(huán)境下不可用
- object_getClassName
獲取一個(gè)對(duì)象的類(lèi)名
const char * object_getClassName(id obj);
- object_getClass
返回一個(gè)對(duì)象的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
修改實(shí)例的類(lèi) 返回之前的類(lèi)的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類(lèi)型的變量類(lèi)型
const char * ivar_getTypeEncoding(Ivar v);
- ivar_getOffset
返回變量的偏移量
ptrdiff_t ivar_getOffset(Ivar v);
Associative References
- objc_setAssociatedObject
給一個(gè)對(duì)象添加協(xié)議鍵值
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);
objc_setAssociatedObject(self,&flashColorKey, flashColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
給分類(lèi)添加協(xié)議屬性時(shí)用到
- objc_getAssociatedObject
獲取對(duì)象的協(xié)議值
id objc_getAssociatedObject(id object, const void *key);
給分類(lèi)添加協(xié)議屬性時(shí)用到
- objc_removeAssociatedObjects
移除對(duì)象的所有協(xié)議
void objc_removeAssociatedObjects(id object);
一般通過(guò)將value設(shè)置成nil來(lái)移除協(xié)議關(guān)系,如果用該方法會(huì)影響別的協(xié)議
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
方法調(diào)用
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
方法調(diào)用返回一個(gè)結(jié)構(gòu)體
void method_invoke_stret(id receiver, Method m, ...);
- method_getName
通過(guò)一個(gè)Method類(lèi)型返回SEL類(lèi)型
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
通過(guò)Method對(duì)象獲取方法的IMP地址
IMP method_getImplementation(Method m);
- method_getTypeEncoding
通過(guò)Method的對(duì)象返回一個(gè)字符串,描述方法的參數(shù)及返回值
const char * method_getTypeEncoding(Method m);
Method method = class_getInstanceMethod([Person class], @selector(printName));
NSLog(@"----%@",[NSString stringWithUTF8String:method_getTypeEncoding(method)]);
- method_copyReturnType
通過(guò)Method的對(duì)象拷貝返回值的字符串 要使用free()方法釋放
char * method_copyReturnType(Method m);
Method method = class_getInstanceMethod([Person class], @selector(getPrintName:));
NSLog(@"----%@",[NSString stringWithUTF8String:method_copyReturnType(method)]);
- method_copyArgumentType
按index返回字符串參數(shù)的類(lèi)型 要使用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
返回參數(shù)的個(gè)數(shù)
unsigned int method_getNumberOfArguments(Method m);
- method_setImplementation
給方法設(shè)置新的實(shí)現(xiàn)地址 返回舊的方法地址
IMP method_setImplementation(Method m, IMP imp);
- method_exchangeImplementations
交互兩個(gè)方法的實(shí)現(xiàn)地址
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 動(dòng)態(tài)庫(kù)及靜態(tài)庫(kù)名稱(chēng)的字符串?dāng)?shù)組
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
返回一個(gè)字符串路徑,顯示該類(lèi)屬于哪個(gè)庫(kù)
const char * class_getImageName(Class cls);
const char * name = class_getImageName([Person class]);
NSLog(@"-----%@",[NSString stringWithUTF8String:name]);
- objc_copyClassNamesForImage
獲取指點(diǎn)庫(kù)中所有類(lèi)的字符數(shù)組名
const char * _Nonnull * objc_copyClassNamesForImage(const char *image, unsigned int *outCount);
Working with Selectors
- sel_getName
獲取SEL類(lèi)型方法的字符串名稱(chēng)
const char * sel_getName(SEL sel);
- sel_registerName
在runtime系統(tǒng)中注冊(cè)方法
SEL sel_registerName(const char *str);
- sel_getUid
在runtime系統(tǒng)中注冊(cè)方法
SEL sel_getUid(const char *str);
- sel_isEqual
判斷兩個(gè)方法是不是相等
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
返回屬性的字符名稱(chēng)
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);