runtime 方法介紹

Objective-C Runtime

Runtime

Working with Classes

  1. class_getName
    返回類(lèi)的名字
const char  * name=class_getName([Person class]);
NSLog(@"name=%s",name);
NSString *userName=[NSString stringWithUTF8String:name];
NSLog(@"userName=%@",userName);

  1. 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);

  1. class_isMetaClass
    返回該類(lèi)是否是元類(lèi)
BOOL isMeta = class_isMetaClass([NSObject class]);
  1. class_getInstanceSize
    返回該類(lèi)實(shí)例的大小
size_t size = class_getInstanceSize([Person class]);
    NSLog(@"%zu",size);
  1. 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]);
  1. 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);
  1. 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);
  1. 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];
    }
  1. class_addProtocol
    給一個(gè)已有的類(lèi)添加協(xié)議
BOOL class_addProtocol(Class cls, Protocol *protocol);
BOOL sucess = class_addProtocol([Person class],_test);
  1. 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ù)組
  1. 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];
   }
  1. class_setIvarLayout
    設(shè)置Ivar 屬性修飾符
void class_setIvarLayout(Class cls, const uint8_t *layout);
  1. 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];
    }
  1. class_setWeakIvarLayout
    設(shè)置Ivar weak修飾符
void class_setWeakIvarLayout(Class cls, const uint8_t *layout);
  1. 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]);
  1. 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]);
    }
  1. 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))]);
  1. class_getClassMethod
    獲取類(lèi)中指定的類(lèi)的Method
Method class_getClassMethod(Class cls, SEL name);
  1. 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]);
    }
  1. 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添加方法,然后在去替換
  1. class_getMethodImplementation
    獲取類(lèi)中指定方法的方法指針
IMP class_getMethodImplementation(Class cls, SEL name);
 IMP methodImp = class_getMethodImplementation([Person class], @selector(printName));
    NSLog(@"%ld",(long)methodImp);
  1. class_respondsToSelector
    是否類(lèi)的實(shí)例能夠響應(yīng)該方法
BOOL class_respondsToSelector(Class cls, SEL sel);

可使用下列方法替換:

  • respondsToSelector:
  • instancesRespondToSelector:
  1. 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);
}
  1. class_conformsToProtocol
    判斷該類(lèi)是否遵循協(xié)議
BOOL class_conformsToProtocol(Class cls, Protocol *protocol);

可用NSObject里邊的conformsToProtocol:替換

Adding Classes

  1. 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)中
  1. objc_disposeClassPair
    銷(xiāo)毀一個(gè)類(lèi)及它的的元類(lèi)
void objc_disposeClassPair(Class cls);

當(dāng)該類(lèi)的實(shí)例及子類(lèi)存在時(shí),不能調(diào)用該方法

  1. objc_registerClassPair
    注冊(cè)一個(gè)類(lèi)
void objc_registerClassPair(Class cls);

Instantiating Classes

  1. class_createInstance
    創(chuàng)建一個(gè)類(lèi)的實(shí)例,且默認(rèn)分配內(nèi)存空間
id class_createInstance(Class cls, size_t extraBytes);
  1. objc_constructInstance
    幢一個(gè)類(lèi)的實(shí)例,且分配實(shí)例的字節(jié)大小
id objc_constructInstance(Class cls, void *bytes);
  1. objc_destructInstance
    銷(xiāo)毀了一個(gè)類(lèi)的實(shí)例沒(méi)有釋放內(nèi)存并刪除任何相關(guān)的引用
void * objc_destructInstance(id obj);

Working with Instances

  1. object_copy
    返回一個(gè)對(duì)象的拷貝
id object_copy(id obj, size_t size);
  1. object_dispose
    釋放一個(gè)對(duì)象的內(nèi)存
id object_dispose(id obj);
  1. 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)境下不可用

  1. 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)境下不可用

  1. object_getClassName
    獲取一個(gè)對(duì)象的類(lèi)名
const char * object_getClassName(id obj);
  1. 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))]);
  1. 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

  1. ivar_getName
    返回變量的名字
const char * ivar_getName(Ivar v);
  1. ivar_getTypeEncoding
    返回string類(lèi)型的變量類(lèi)型
const char * ivar_getTypeEncoding(Ivar v);
  1. ivar_getOffset
    返回變量的偏移量
ptrdiff_t ivar_getOffset(Ivar v);

Associative References

  1. 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í)用到

  1. objc_getAssociatedObject
    獲取對(duì)象的協(xié)議值
id objc_getAssociatedObject(id object, const void *key);

給分類(lèi)添加協(xié)議屬性時(shí)用到

  1. objc_removeAssociatedObjects
    移除對(duì)象的所有協(xié)議
void objc_removeAssociatedObjects(id object);

一般通過(guò)將value設(shè)置成nil來(lái)移除協(xié)議關(guān)系,如果用該方法會(huì)影響別的協(xié)議

Sending Messages

  1. 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

  1. 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);
  1. method_invoke_stret
    方法調(diào)用返回一個(gè)結(jié)構(gòu)體
void method_invoke_stret(id receiver, Method m, ...);
  1. 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)]);
  1. method_getImplementation
    通過(guò)Method對(duì)象獲取方法的IMP地址
IMP method_getImplementation(Method m);
  1. 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)]);
  1. 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)]);
  1. 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)]);
  1. method_getNumberOfArguments
    返回參數(shù)的個(gè)數(shù)
unsigned int method_getNumberOfArguments(Method m);
  1. method_setImplementation
    給方法設(shè)置新的實(shí)現(xiàn)地址 返回舊的方法地址
IMP method_setImplementation(Method m, IMP imp);
  1. 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

  1. 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]]);
    }
  1. class_getImageName
    返回一個(gè)字符串路徑,顯示該類(lèi)屬于哪個(gè)庫(kù)
const char * class_getImageName(Class cls);
const char * name = class_getImageName([Person class]);
    NSLog(@"-----%@",[NSString stringWithUTF8String:name]);
  1. objc_copyClassNamesForImage
    獲取指點(diǎn)庫(kù)中所有類(lèi)的字符數(shù)組名
const char * _Nonnull * objc_copyClassNamesForImage(const char *image, unsigned int *outCount);

Working with Selectors

  1. sel_getName
    獲取SEL類(lèi)型方法的字符串名稱(chēng)
const char * sel_getName(SEL sel);
  1. sel_registerName
    在runtime系統(tǒng)中注冊(cè)方法
SEL sel_registerName(const char *str);
  1. sel_getUid
    在runtime系統(tǒng)中注冊(cè)方法
SEL sel_getUid(const char *str);
  1. sel_isEqual
    判斷兩個(gè)方法是不是相等
BOOL sel_isEqual(SEL lhs, SEL rhs);

Working with Protocols

  1. objc_getProtocol
    Returns a specified protocol.
  2. objc_copyProtocolList
    Returns an array of all the protocols known to the runtime.
  3. objc_allocateProtocol
    Creates a new protocol instance.
  4. objc_registerProtocol
    Registers a newly created protocol with the Objective-C runtime.
  5. protocol_addMethodDescription
    Adds a method to a protocol.
  6. protocol_addProtocol
    Adds a registered protocol to another protocol that is under construction.

Working with Properties

  1. property_getName
    返回屬性的字符名稱(chēng)
const char * property_getName(objc_property_t property);
  1. property_getAttributes
    返回屬性的字符
Returns the attribute string of a property.
  1. property_copyAttributeValue
    Returns the value of a property attribute given the attribute name.
char * property_copyAttributeValue(objc_property_t property, const char *attributeName);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容