1、什么是RunTime
RunTime即運行時米母,objective-c是一種運行時的語言,什么是運行時呢,運行時就是在程序運行的時候才去確定我們的對象的類型和需要調(diào)用類和對象相對應(yīng)的方法裁替。
2、RunTime的用法
RunTime是在我們程序運行的時候才去確定我們的對象類型貌笨,和調(diào)用類與對象相對應(yīng)的方法弱判,屬性等,所以我們可以在程序運行時去修改對象的屬性锥惋,方法昌腰,修改類。
3膀跌、RunTime的體現(xiàn)
Animal *a = [[Animal alloc] init];
[a eat];//eat是一個實例方法
//底層運行的狀態(tài)
[a performSelector:@selector(eat)];
objc_msgSend(a,@selector(eat));
//類方法也是一樣
[Animal eat];
//底層運行的狀態(tài)
Class animalClass = [Animal class];
[[Animal class] performSelector(eat)];
objc_msgSend(animalClass,@selector(eat));
從我們調(diào)用方法到底層運行的順序是:實例方法的調(diào)用遭商,然后是底層進行performSelector:然后到objc_msgSend。
4捅伤、RunTime的使用場景
- 1株婴、使用RunTime進行方法的調(diào)換。
很常見的一個例子暑认,在我們進行圖片加載的時候困介,我們有這樣一個需求,在加載圖片之后判斷這個圖片是否為空蘸际,如果為空就輸出error座哩。我們首先想到就是使用分類來做,使用分類來做是沒有問題的粮彤,前提是你還沒有寫多少代碼根穷,如果你的項目很龐大姜骡,不可能全部都重新修改你加載圖片的方法吧,所以說使用分類不是不行屿良,而是很不方便圈澈,那么我們需要怎么做呢?我們要坐的就是在分類里面對我們的方法進行替換尘惧。首先我們需要寫一個我們用來替換原本加載圖片的方法的方法康栈。
+(UIImage *)judgeImageName:(NSString *)name{
UIImage \*image = [UIImage imageNamed:name];
if (image == nil) {
NSLog(@"error");
}
return image;
}
//然后在分類的+(void)load;方法進行方法的替換
+(void)load{
Method imageNamedMethod = class_getClassMethod([UIImage class],@selector(imageNamed));
Method judgeimageNamedMethod = class_getClassMethod([UIImage class],@selector(judgeImageName));
Method_exchangeImplementations(imageNamedMethod,judgeimageNamedMethod);
}
需要注意的是,我們使用了這種做法來替換方法之后不能去調(diào)用我們在分類中寫的方法了喷橙,原因是你調(diào)用這個方法啥么,這個方法調(diào)用原來的方法,原來的方法又去調(diào)用我們寫的方法贰逾,這樣的話就是一個死循環(huán)悬荣。
- 2、使用RunTime添加屬性
分類是默認不能添加屬性的疙剑,就算我們用@property聲明了一個屬性氯迂,該屬性的set和get只會聲明而不會實現(xiàn)。但是我們可以使用RunTime來為分類添加屬性言缤。
@property (nonatomic, strong)NSString *age
-(void)setAge:(NSString *)name{
objc_setAssociatedObject(self,@"age",age,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
objc_setAssociatedObject
中的參數(shù):
第一個參數(shù)為在哪里添加這個屬性囚戚,這里就是self
第二個參數(shù)為屬性名
第三個參數(shù)為屬性值
第四個參數(shù)為屬性的形式,一般有以下幾種
OBJC_ASSOCIATION_ASSIGN = 0, //弱對象
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //強引用轧简,非原子性
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //指定對象賦值驰坊,非原子性
OBJC_ASSOCIATION_RETAIN = 01401, //強引用, 原子性
OBJC_ASSOCIATION_COPY = 01403 //指定對象賦值哮独,原子性
}
-(NSString *)age{
objc_getAssociatedObject(self,@"age");
}
objc_getAssociatedObject
中的參數(shù):
第一個參數(shù)為獲取哪個對象里面關(guān)聯(lián)的屬性拳芙。
第二個參數(shù)為什么屬性,其實就是屬性名皮璧。