Runtime消息传递机制
2019-01-22 本文已影响73人
昵称是乱起的
先看下整个Class的底层结构
image.pngobjc_msgSend的源码是汇编实现的
objc_msgSend的执行流程01-消息发送
image.png如果是从class_rw_t中查找方法,已经排序的采用二分查找,没有排序的遍历查找
receiver通过isa指针找到receiverClass
receiverClass通过superclass指针找到superClass
objc_msgSend的执行流程02-动态方法解析
image.png动态解析过后,会重新走“消息发送”的流程,“从receiverClass的cache中查找方法”这一步开始执行
开发者可以实现以下方法,来动态添加方法实现
+resolveInstanceMethod:
+resolveClassMethod:
#InstanceMethod第1种写法
- (void)other
{
NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel == sel_registerName("test")) {
Method method = class_getInstanceMethod(self, sel_registerName("test"));
class_addMethod(self, sel, method_getImplementation(method), method_getTypeEncoding(method));
return YES;
}
return [super resolveInstanceMethod:sel];
}
#InstanceMethod第2种写法
void c_other(id self, SEL _cmd)
{
NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel == @selector(test)) {
class_addMethod(self, sel, (IMP)c_other, "v16@0:8");
return YES;
}
return [super resolveInstanceMethod:sel];
}
#InstanceMethod第3种写法
struct method_t {
SEL sel;
char *types;
IMP imp;
};
- (void)other
{
NSLog(@"%s",__func__);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
if (sel == @selector(test)) {
struct method_t *method = (struct method_t *)class_getInstanceMethod(self, @selector(other));
class_addMethod(self, sel, method->imp, method->types);
return YES;
}
return [super resolveInstanceMethod:sel];
}
#ClassMethod写法
void c_other(id self, SEL _cmd)
{
NSLog(@"c_other - %@ - %@", self, NSStringFromSelector(_cmd));
}
+ (BOOL)resolveClassMethod:(SEL)sel
{
if (sel == @selector(test)) {
class_addMethod(object_getClass(self), sel, (IMP)c_other, "v16@0:8");
return YES;
}
return [super resolveClassMethod:sel];
}
objc_msgSend的执行流程03-消息转发
image.png+ (id)forwardingTargetForSelector:(SEL)aSelector
{
if (aSelector == @selector(test)) return [[Person alloc] init];
return [super forwardingTargetForSelector:aSelector];
}
//上面return NO才会来到这里
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
if (aSelector == @selector(test:)) {
return [NSMethodSignature signatureWithObjCTypes:"i@:i"];
}
return [super methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
[anInvocation invokeWithTarget:[[Person alloc] init]];
}
@dynamic value;// 提醒编译器不要自动生成setter和getter的实现、不要自动生成成员变量
super底层
[self class];
objc_msgSend(self, sel_registerName("class"))
[super superclass];
objc_msgSendSuper({self,class_getSuperclass(objc_getClass("Person"))}, sel_registerName("class")))