runtime 執行時機制
阿新 • • 發佈:2018-11-04
runtime是一套比較底層的純C語言API, 屬於1個C語言庫, 包含了很多底層的C語言API。 在我們平時編寫的OC程式碼中, 程式執行過程時, 其實最終都是轉成了runtime的C語言程式碼, runtime算是OC的幕後工作者 比如說,下面一個建立物件的方法中, 舉例: OC : [[MJPerson alloc] init] runtime : objc_msgSend(objc_msgSend("MJPerson" , "alloc"), "init")
runtime是屬於OC的底層, 可以進行一些非常底層的操作(用OC是無法現實的, 不好實現)
- 在程式執行過程中, 動態建立一個類(比如KVO的底層實現)
- 在程式執行過程中, 動態地為某個類新增屬性\方法, 修改屬性值\方法
-
遍歷一個類的所有成員變數(屬性)\所有方法 例如:我們需要對一個類的屬性進行歸檔解檔的時候屬性特別的多,這時候,我們就會寫很多對應的程式碼,但是如果使用了runtime就可以動態設定! 例如程式碼舉例 一、
2> 相關應用
- NSCoding(歸檔和解檔, 利用runtime遍歷模型物件的所有屬性)
- 字典 --> 模型 (利用runtime遍歷模型物件的所有屬性, 根據屬性名從字典中取出對應的值, 設定到模型的屬性上)
- KVO(利用runtime動態產生一個類)
- 用於封裝框架(想怎麼改就怎麼改) 這就是我們runtime機制的只要運用方向
3> 相關函式
- objc_msgSend : 給物件傳送訊息
- class_copyMethodList : 遍歷某個類所有的方法
- class_copyIvarList : 遍歷某個類所有的成員變數
- class_..... 這是我們學習runtime必須知道的函式
#import <objc/runtime.h>
#import <objc/message.h>
舉例一、獲取一個類的成員變數 ivar_getName
@class Person; -(void)encodeWithCoder:(NSCoder )encoder { unsigned int count = 0; Ivar ivars = class_copyIvarList([Person class], &count); for (int i = 0; i<count; i++) { // 取出i位置對應的成員變數 Ivar ivar = ivars[i]; // 檢視成員變數 const char *name = ivar_getName(ivar); // 歸檔 NSString *key = [NSString stringWithUTF8String:name]; id value = [self valueForKey:key]; [encoder encodeObject:value forKey:key]; } free(ivars); } -(id)initWithCoder:(NSCoder *)decoder { if (self = [super init]) { unsigned int count = 0; Ivar *ivars = class_copyIvarList([Person class], &count); for (int i = 0; i<count; i++) { // 取出i位置對應的成員變數 Ivar ivar = ivars[i]; // 檢視成員變數 const char *name = ivar_getName(ivar); // 歸檔 NSString *key = [NSString stringWithUTF8String:name]; id value = [decoder decodeObjectForKey:key]; // 設定到成員變數身上 [self setValue:value forKey:key]; } free(ivars); } return self; }
舉例二、拓展成員變數(get 、set 方法)
@interface LolaTrackInfo (AddressParse)
@property (nonatomic) BOOL everParsedAddress;
@end
@implementation LolaTrackInfo (AddressParse)
static char parseAdKey;
-(BOOL)everParsedAddress
{
NSNumber *b = objc_getAssociatedObject(self, &parseAdKey);
return b.boolValue;
}
-(void)setEverParsedAddress:(BOOL)everParsedAddress
{
objc_setAssociatedObject(self, &parseAdKey, [NSNumber numberWithBool:everParsedAddress], OBJC_ASSOCIATION_RETAIN);
}
@end
舉例三、方法交換
@implementation UIViewController (GlobalConfig)
+ (void)load
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(viewDidLoad);
SEL swizzledSelector = @selector(mob_viewDidLoad);
method_exchangeImplementations(class_getInstanceMethod(class, originalSelector), class_getInstanceMethod(class, swizzledSelector));
});
}
- (void)mob_viewDidLoad
{
[self mob_viewDidLoad];
//。。。 下面一般是 所有 UIViewController 都要執行的內容
}
@end
參考:https://my.oschina.net/panyong/blog/298631
http://www.cnblogs.com/CoderAlex/p/5025958.html