一、定义:
Runtime:运行时 就是代码编译时.被装载到内存中去了
二、Runtime的三种调用方式如图:
1.Objctive-C Code方式调用。
2.RunTime API
3.framework&Service
三、探索objc_msgSend流程
通过clang生成ViewController.cpp文件,生成方式如下:
1.终端->cd到你所需要的文件目录下。
方法1:
xcrun -sdk iphonesimulator clang -rewrite-objc ViewController.m
方法2:
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk ViewController.m
回归正题探索msgSend准备工作:创建一个类
@interface LGPerson : LGTeacher
- (void)sayHello;
- (void)sayNB:(NSString *)name;
//测试方法
- (void)testFuncation;
@end
@implementation LGPerson
- (void)sayNB:(NSString *)name{
NSLog(@"%s:666----%@",__func__,name);
}
- (void)sayHello{
NSLog(@"%s:hello",__func__);
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
// sel_registerName = @seletor() = NSSeletorFromString()
// 方法: 消息 : (消息的接受者 . 消息主体)
LGPerson *person = [LGPerson alloc];
LGTeacher *teacher = [LGTeacher alloc];
objc_msgSend(person, sel_registerName("sayNB:"),@"测试");
objc_msgSend(person, sel_registerName("sayHello"));
//本类没有相应的方法,会去查询父类。找到了会进行消息发送
struct objc_super lgsuper;
lgsuper.receiver = person;
lgsuper.super_class = [LGTeacher class];
objc_msgSendSuper(&lgsuper, sel_registerName("sayHello"));
}
return 0;
}
结果如下:
objc_msgSend的解析
在.cpp文件发现objc_msgSend,那么objc_msgSend的底层实现应该在汇编里。
底层实现使用汇编的好处:1.效率高,速度快。2.类型的不确定性。所以一般是不带参数进行消息发送
四、objc_msgSend初探
这里我们用的是arm64,消息接受者 : 对象 - ISA - 方法(类) - cache_t - methodlist,在源码中搜素`objc_msgSend`,->objc-msg-arm64.s文件。
找到入口函数:`ENTRY _objc_msgSend`->出口函数:`END_ENTRY _objc_msgSend`
#endif
ENTRY _objc_msgSend
UNWIND _objc_msgSend, NoFrame
//cmp寄存器 p0:判断消息接收是否存在。
cmp p0, #0 // nil check and tagged pointer check
#if SUPPORT_TAGGED_POINTERS //:若支持SUPPORT_TAGGED_POINTERS类型,则执行下面方法
b.le LNilOrTagged // (MSB tagged pointer looks negative)
#else
b.eq LReturnZero
#endif
ldr p13, [x0] // p13 = isa
GetClassFromIsa_p16 p13 // p16 = 获取类class,调用GetClassFromIsa_p16,
LGetIsaDone:
// calls imp or objc_msgSend_uncached
//在缓存中获取imp的值
CacheLookup NORMAL, _objc_msgSend
#if SUPPORT_TAGGED_POINTERS
LNilOrTagged:
b.eq LReturnZero // nil check
// tagged
adrp x10, _objc_debug_taggedpointer_classes@PAGE
add x10, x10, _objc_debug_taggedpointer_classes@PAGEOFF
ubfx x11, x0, #60, #4
ldr x16, [x10, x11, LSL #3]
adrp x10, _OBJC_CLASS_$___NSUnrecognizedTaggedPointer@PAGE
add x10, x10, _OBJC_CLASS_$___NSUnrecognizedTaggedPointer@PAGEOFF
cmp x10, x16
b.ne LGetIsaDone
// ext tagged
adrp x10, _objc_debug_taggedpointer_ext_classes@PAGE
add x10, x10, _objc_debug_taggedpointer_ext_classes@PAGEOFF
ubfx x11, x0, #52, #8
ldr x16, [x10, x11, LSL #3]
b LGetIsaDone
// SUPPORT_TAGGED_POINTERS
#endif
LReturnZero:
// x0 is already zero
mov x1, #0
movi d0, #0
movi d1, #0
movi d2, #0
movi d3, #0
ret
END_ENTRY _objc_msgSend
总流程如下: