標籤:
runtime的運用: (以下代碼全部都基於Dog類建立的一個對象:dog)
1.使用id類型來建立變數以便接受不同類型的對象
2.使用 [person performSelector:@selector(test2:) withObject:@"傳入參數"];來動態調用方法;
3.使用objc_setAssociatedObject(id object,const void *key,id value,objc_AssociationPolicy policy)為對象object添加額外的儲存空間.
4.動態copy對象
在MRC模式下使用:
Dog *dog = [Dognew];
dog.name = @"1234";
dog.age = 3;
Dog *copyDog = object_copy(dog,sizeof(dog));
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,"[email protected]:@@");
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執行的是在本控制器裡輸出的語句.
iOS runtime運用執行個體