Runtime介紹
運行時,OC就是運行時機制,最主要的是消息機制。
對于C語言,函數的調用在編譯的過程中會決定調用哪個函數。
對于OC,則屬于動態調用過程,只有在真正運行的時候才會根據函數名找到對應的函數。
Runtime作用
1.發送消息
objc_msgSend
方法調用的本質,就是讓對象發送消息。
2.交換方法method_exchangeImplementations
系統自帶的方法功能不夠時,想給系統自帶的方法擴展一些功能,并且保持原有的功能。
3.動態添加方法class_addMethod
如果一個類的方法很多,加載類到內存的時候耗費資源,需要給每個方法生成映射表,可以使用動態給某個類,添加方法解決。
4.動態添加屬性objc_setAssociatedObject
給一個類聲明屬性,其實本質就是給這個類添加關聯,并不是直接把這個值的內存空間添加到類存空間,就是對象本身的屬性可以關聯到另外一個內存中。
發送消息
使用運行時的第一步:
1.#import <objc/message.h>
2.xcode-->build settings->搜索msg
Paste_Image.png
我們先創建一個Person對象,創建一個類方法,一個對象方法,如下代碼所示:
#import "Person.h"
@implementation Person
+ (void)eat
{
NSLog(@"類方法——吃飯");
}
- (void)eat
{
NSLog(@"對象方法——吃面");
}
@end
我們在控制器中調用,首先,#import "Person.h"
Person * p = [[Person alloc] init];
//我們一般調用對象方法,都會這樣寫:[p eat],
//現在用runtime讓對象p發送一個消息。
objc_msgSend(p, @selector(eat));
//按照以前,我們調用類方法,都會是這樣寫的
//[Person eat] 那使用runtime調用類方法,跟調用對象方法類似。
//獲取類對象
Class personClass = [Person class];
//運行時:拿到類對象,調用類方法。
objc_msgSend(personClass, @selector(eat));
ok,我們運行程序:
2017-01-18 10:46:22.940 [70808:6452367] 對象方法——吃面
2017-01-18 10:46:22.940 [70808:6452367] 類方法——吃飯
現在我再寫一個對象方法,添加一個值,在控制器中傳過去。
- (void)ride:(int)age
{
NSLog(@"%d",age);
}
控制器中調用
objc_msgSend(p, @selector(ride:),10);
運行結果:
2017-01-18 10:51:41.083 [71101:6456914] 10
如果我們不用runtime來發送消息,還有另外一種方式也可以調用類方法和對象方法,那就是SEL。
Person * p = [[Person alloc] init];
//SEL:方法編號,根據方法編號就可以找到對應方法實現,屬于動態調用
[p performSelector:@selector(eat)];
//獲取類對象
//類名調用類方法,本質類名轉換成類對象
Class personClass = [Person class];
[personClass performSelector:@selector(eat)];
運行結果一樣:
2017-01-18 10:46:22.940 [70808:6452367] 對象方法——吃面
2017-01-18 10:46:22.940 [70808:6452367] 類方法——吃飯