iOS runtime運用實例

runtime的運用:  (如下代碼所有都基於Dog類建立的一個對象:dog)數組

     1.使用id類型來建立變量以便接受不一樣類型的對象spa

     2.使用 [person performSelector:@selector(test2:) withObject:@"傳入參數"];來動態的調用方法;orm

3.使用objc_setAssociatedObject(id object,const void *key,id value,objc_AssociationPolicy policy)爲對象object添加額外的存儲空間.對象

4.動態copy對象ci

在MRC模式下使用:字符串

 

 

    Dog *dog = [Dognew];get

    dog.name = @"1234";cmd

    dog.age = 3;源碼

    

    Dog *copyDog = object_copy(dog,sizeof(dog));string

5.動態設置對象的歸屬類object_setClass 或者得到對象的歸屬類

object_setClass以下列代碼:

 

  Dog *dog = [Dognew];

    NSLog(@"dog.class==%@",[dogclass]);

    NSLog(@"%@",object_setClass(dog, [Catclass])); //Object_setClass的返回值爲對象原來的所屬類

    NSLog(@"dog.class==%@",[dogclass]);

將輸出:

 

dog.class==Dog

Dog

dog.class==Cat

 

object_getClass 以下代碼:

    Dog *dog = [Dognew];

    Class class = object_getClass(dog);

    NSLog(@"%@",class);

將輸出:Dog 

也就是動態的得到dog對象的所屬類

 

5.respondsToSelector 以及 performSelector

respondsToSelector,用來判斷對象是否能夠調用對應的方法,傳入一個SEL類型的值

performSelector用來直接使用對象調用方法,傳入一個SEL類型的參數,常常將二者結合來用,示例以下:

 

 

 

if ([dog respondsToSelector:@selector(funOfDog)]) {

 

 

 

        [dog performSelector:@selector(funOfDog)];

 

 

 

    }else if([dogrespondsToSelector:@selector(funOfCat)]){

 

 

 

        [dog performSelector:@selector(funOfCat)];

 

 

 

    }

 

 

判斷dog類能夠相應那種方法而且直接調用它.

6.使用object_getClassName獲取類名,只不過是C+字符串的格式

const char * className =object_getClassName(dog);

   printf("%s",className);

輸出:Dog

 

7.爲對象添加方法

    爲Dog類添加私有方法,由於這個方法是動態添加的,因此只能使用使用respondsToSelector來動態的調用這個方法,不然的話,編譯是不經過的,由於在被添加的類中,該方法即沒有實現也沒有聲明.

    class_addMethod([Dogclass], @selector(dogAddFun:str2:), (IMP)funOfAdd,"i@:@@");

    if ([dog respondsToSelector:@selector(dogAddFun:str2:)]) {

       int number =  [dogperformSelector:@selector(dogAddFun:str2:)withObject:@"1234"withObject:@"5678"];

        NSLog(@"%d",number);

    }else

        NSLog(@"方法沒有添加成功");

  
    funOfAdd方法定義:

int funOfAdd(idself,SEL_cmd,NSString *str,NSString* str2){

    return (int)(str.length + str2.length);

}  //返回兩個字符串長度相加的和

8.獲取一個類的全部方法  class_copyMethodList

 

    u_int count;

    Method *methods = class_copyMethodList([dog class], &count);

    for (int i = 0 ; i < count; i ++){

        SEL name = method_getName(methods[i]);

        printf("%s\n",sel_getName(name));

    }

    其中,class_copyMethodList的兩個參數分別爲類名和統計方法數量的無符號整形的變量地址,其返回值爲一個包含該類全部objc_method方法的數組

    method_getName傳入的參數是該類中的objc_method對象,返回值爲該方法對應的SEL,其在runtime源碼中的實現以下:

 

 

SEL method_getName(Method m)

 

 

{

 

 

    if (!m) return NULL;

 

 

    return oldmethod(m)->method_name;

 

 

}

 

    sel_getName(name)則是經過SEL獲取該SEL對應的方法名

 

9.獲取一個類的全部屬性名

 

 u_int count;

    objc_property_t* properites = class_copyPropertyList([dog class], &count);

    for(int i = 0 ; i < count;i ++){

        const char* name= property_getName(properites[i]);

        printf("%s\n",name);

    }

   class_copyPropertyList返回一個包含該類全部屬性的數組,property_getName得到該objc_property_t對應的屬性名    的字符串.

 

10.系統類方法的替換

     能夠互換兩個方法的實現 ,可是沒感受有什麼用途 ,估計是沒遇到有次需求的問題  

    Method method1 = class_getInstanceMethod([NSString class],@selector(lowercaseString));

    Method method2 = class_getInstanceMethod([NSString class],@selector(uppercaseString));

    method_exchangeImplementations(method1, method2);

    NSLog(@"%@",[@"aaaaaa" lowercaseString]);

    NSLog(@"%@",[@"BBBBB" uppercaseString]);

 
11.實現自定義方法的替換

    Method method1 = class_getInstanceMethod([dog class],@selector(funOfDog));

    Method funMethod = class_getInstanceMethod([self class],@selector(replaseFun));

    IMP imp = method_getImplementation(funMethod);

 

    method_setImplementation(method1, imp);

    [dog funOfDog];

    

    funOfDog是dog類裏定義的方法,replaseFun是在調用控制器裏定義的方法,兩個方法都只有一條輸出語句,執行完上述語句後,dog調用funOfDog執行的是在本控制器裏輸出的語句.

相關文章
相關標籤/搜索