首页 > 代码库 > Objective-C runtime 机制

Objective-C runtime 机制

[obj foo] 等同于 obj_msgSend(obj,@selector(foo))

类的底层结构代码

struct objc_class {
 Class isa OBJC_ISA_AVAILABILITY; //isa指针   
#if !__OBJC2__ Class
super_class OBJC2_UNAVAILABLE; // 父类
const char *name OBJC2_UNAVAILABLE; // 类名
long version OBJC2_UNAVAILABLE; // 类的版本信息,默认为0
long info OBJC2_UNAVAILABLE; // 类信息
long instance_size OBJC2_UNAVAILABLE; // 类占据的内存大小
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; // 成员变量链表
struct objc_method_list **methodLists OBJC2_UNAVAILABLE; // 方法链表
struct objc_cache *cache OBJC2_UNAVAILABLE; // 方法缓存列表
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 协议链表
 #endif
 } OBJC2_UNAVAILABLE;

 objc 在向一个对象发送消息时,runtime库会根据对象的isa指针找到该对象实际所属的类,然后在该类的方法列表以及其父类方法列表中寻找方法运行。如果在层层的寻找中均位找到方法的实现,
 就会抛出unrecognized selector sent to XXX的异常,导致程序奔溃.
 在这奔溃前,oc运行时提供了三次拯救程序的机会
 
 1、Method resolution ,动态方法解析阶段
 对应的具体方法是+(BOOL)resolveInstanceMethod:(SEL)sel 和+(BOOL)resolveClassMethod:(SEL)sel,
 当方法是实例方法时调用前者,当方法为类方法时,调用后者。这个方法设计的目的是为了给类利用 class_addMethod 添加方法的机会。
 
 2、fowarding 方法转发,备援接收者阶段
 对象的具体方法是-(id)forwardingTargetForSelector:(SEL)aSelector ,
 此时,运行时询问能否把消息转给其他接收者处理,也就是此时系统给了个将这个 SEL 转给其他对象的机会。
 
 3、 fowarding 方法转发,完整消息转发阶段
 对应方法-(void)forwardInvocation:(NSInvocation *)anInvocation,这是消息转发流程的最后一个环节。参数 anInvocation 中包含未处理消息的各种信息(selector\target\参数...)。
 在这个方法中,可以把 anInvocation 转发给多个对象,与第二步不同,第二步只能转给一个对象
 
 如果上述3个方法都没有来处理这个消息,就会进入 NSObject 的-(void)doesNotRecognizeSelector:(SEL)aSelector方法中,抛出异常

总结一下整个消息转发的流程:

技术分享 

代码:

#import "ViewController.h"

@interface ViewController ()

@property (weak, nonatomic) IBOutlet UILabel *displayLabel;
- (IBAction)buttonTest:(UIButton *)sender;
@end

@implementation ViewController

- (IBAction)buttonTest:(UIButton *)sender {
    NSLog(@"--1--");
    [self performSelector:@selector(setText:) withObject:@"hello"];
}


+(BOOL)resolveInstanceMethod:(SEL)sel
{
    NSLog(@"--2--");
    return NO;
}
//+(BOOL)resolveClassMethod:(SEL)sel
//{
//    NSLog(@"--2--");
//    return NO;
//}

-(id)forwardingTargetForSelector:(SEL)aSelector
{
    NSLog(@"--3--");
    return nil;
}

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSLog(@"--4--");
   NSMethodSignature *signature= [super methodSignatureForSelector:aSelector];
    if (!signature) {
        signature=[self.displayLabel methodSignatureForSelector:aSelector];
    }
    
    return signature;
}

-(void)forwardInvocation:(NSInvocation *)anInvocation
{
    NSLog(@"--5--");
    SEL seletor=[anInvocation selector];
    if([self.displayLabel respondsToSelector:seletor]){
        [anInvocation invokeWithTarget:self.displayLabel];
    }
}

@end

 

 

参考:

链接:iOS消息转发机制详解

链接:OC最实用的runtime总结,面试、工作你看我就足够了!

Objective-C runtime 机制