Runtime 是由匯編, C, C++語言編寫的,可以防方法crash,收集crash信息
OC是一門動態(tài)語言尖啡,Runtime就是提供OC運(yùn)行時的API
編譯時:源代碼翻譯成機(jī)器語言
運(yùn)行時:OC代碼運(yùn)行起來,加載到內(nèi)存
Runtime是OC語言的底層
Runtime API 列表
http://www.reibang.com/p/845f2180722b
調(diào)用runtime 有三種方式
1. OC上層代碼代碼?@selector
2.NSObject ?API 如?isKindOfClass
3. runtime api
Runtime 運(yùn)行,方法調(diào)用
_objc_msgSend使用匯編語言新娜,效率高,能夠根據(jù)未知的指針蝴簇,直接跳轉(zhuǎn)(C實(shí)現(xiàn)不了)
方法查找
匯編部分快速查找?__class_lookupMethodAndLoadCache3 之前
C C++部分慢速查找?__class_lookupMethodAndLoadCache3 之后
方法查找是二分查找, 緩存 + 方法列表(分類方法 + 本身方法杯活,同名分類方法先查找到)
方法查找不到,進(jìn)入動態(tài)方法解析
實(shí)例方法動態(tài)解析
知道會走NSObject 的?+ (BOOL)resolveInstanceMethod:(SEL)sel
類方法動態(tài)解析
void _class_resolveMethod(Class cls, SEL sel, id inst)
{
? ? if (! cls->isMetaClass()) {
? ? ? ? // try [cls resolveInstanceMethod:sel]
? ? ? ? _class_resolveInstanceMethod(cls, sel, inst);
? ? }?
? ? else {
? ? ? ? // try [nonMetaClass resolveClassMethod:sel]
? ? ? ? // and [cls resolveInstanceMethod:sel]
? ? ? ? _class_resolveClassMethod(cls, sel, inst);
? ? ? ? if (!lookUpImpOrNil(cls, sel, inst,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? NO/*initialize*/, YES/*cache*/, NO/*resolver*/))?
? ? ? ? {
? ? ? ? ? ? _class_resolveInstanceMethod(cls, sel, inst);
? ? ? ? }
? ? }
}
if (!lookUpImpOrNil(cls, sel, inst,?
? ? ? ? ? ? ? ? ? ? ? ? ? ? NO/*initialize*/, YES/*cache*/, NO/*resolver*/))?
? ? ? ? {
? ? ? ? ? ? _class_resolveInstanceMethod(cls, sel, inst);
? ? ? ? }
類方法動態(tài)解析熬词,在進(jìn)行resolveClassMethod解析旁钧, 會判斷一次未實(shí)現(xiàn)的方法得到解決沒吸重,沒有的話在進(jìn)行一次resolveInstanceMethod解析
無論類方法還是實(shí)例方法,都會調(diào)用
+ (BOOL)resolveInstanceMethod:(SEL)sel?
在NSObject 中歪今,避免resolveClassMethod或者resolveInstanceMethod找不到造成的死循環(huán)
+ (BOOL)resolveClassMethod:(SEL)sel {
? ? return NO;
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
? ? return NO;
}
類方法動態(tài)解析未解決問題嚎幸,進(jìn)行消息轉(zhuǎn)發(fā)
- (id)forwardingTargetForSelector:(SEL)aSelector
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
- (void)forwardInvocation:(NSInvocation *)anInvocation
在NSObject分類中
- (id)forwardingTargetForSelector:(SEL)aSelector{
? ? NSLog(@"%s",__func__);
//? ? if (aSelector == @selector(run)) {
//? ? ? ? // 轉(zhuǎn)發(fā)給我們的LGStudent 對象
//? ? ? ? return [LGStudent new];
//? ? }
? ? return nil;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
? ? if (aSelector == @selector(run)) {
? ? ? ? // forwardingTargetForSelector 沒有實(shí)現(xiàn) 就只能方法簽名了
? ? ? ? Methodmethod? ? =class_getInstanceMethod(object_getClass(self), @selector(readBook));
? ? ? ? const char *type = method_getTypeEncoding(method);
? ? ? ? return [NSMethodSignature signatureWithObjCTypes: type];
? ? }
? ? return nil;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation{
? ? NSLog(@"%s",__func__);
? ? NSLog(@"------%@-----",anInvocation);
? ? anInvocation.selector = @selector(readBook);
? ? [anInvocationinvoke];
?? ?
?? ?
//? ? NSString *sto = @"奔跑少年";
//? ? anInvocation.target = [LGStudent class];
//? ? [anInvocation setArgument:&sto atIndex:2];
//? ? NSLog(@"%@",anInvocation.methodSignature);
//? ? anInvocation.selector = @selector(run:);
//? ? [anInvocation invoke];
} ?