美文网首页
Objective-C消息发送

Objective-C消息发送

作者: Hunter琼 | 来源:发表于2018-03-26 10:02 被阅读59次

    一 概述:
    Objective-C(简称OC)的Cocoa层的API中有大量的[receiver message]消息发送机制,初学时我们往往把理解为一个object调用了一个method,而往往忽视了"消息机制"这句话的深刻含义,[receiver message]独特机制区别于其他主流语言,这也是很多软件开发者转型iOS 选择Swift原因了.
    二 原理:
    消息发送机制是Runtime通过selector快速查找IMP的过程,有了IMP这个函数指针,就可以执行对应的方法实现.
    [receiver message]会被编译器转换成为:

    // arg1 ,arg2... 表示消息含有的参数
    objc_msgSend(receiver, selector, arg1, arg2, ...)
    

    如果消息的接受者能够找到对应的selector,相当于执行了这个对象方法,否则消息要么被转发,要么临时向接受者动态添加这个 selector 对应的实现内容,要么就干脆崩溃

    IMP:定义为 typedef void (*IMP)(void /* id,SEL,... */);本质是个函数指针,由编译器生成,当发送一条消息之后,最终它会执行方法,就是由该函数指针定的,而IMP这个函数指针就是指向了这个方法的实现.
    三 super
    super是OC的保留字,不是隐式参数,它只是个''编译器指示器',主要是针对父类
    id objc_msgSendSuper(struct objc_super *super,SEL op,...)
    当消息传递给父类的时候,调用objc_msgSendSuper,objc_super 这个结构体会存放当前函数里的self(隐式参数)的super_class,即[self superclass];msgSendSuper从当前对象的父类方法开始,沿着父类继承链查找.最终执行到[super respondsToSelector:@selector(superHasNotThisSelector) ]; 而respondsToSelector这个方法是NSObject方法,而NSObjcet类位于所有类继承的顶端,执行这个方法会找到对应的实现函数!
    四 self
    self是OC的隐式参数,之所以叫隐式参数是因为源代码方法定义中并没有声明这个参数,但我们可以引用它;self本身也是个指针,在每个方法中都有一个self指针,在函数中无法使用,可以使用self -> 成员变量
    五 动态方法
    前面提到某些情况下消息的接受者无法找到对应的selector时,会临时向接受者动态添加这个selector对应的实现内容.
    给某个属性声明@dynamic类型,编译器会认为这个属性相关的方法会动态提供,也就是说编译器不会默认生成属性的setget方法了,而需要我们动态提供,可以通过重载resolveInstanceMethod:resolveClassMethod添加动态方法.
    代码示例如下:

    #import <Foundation/Foundation.h>
    
    @interface AutoMehtodModel : NSObject
    @property(nonatomic,copy)NSString *addAutoMethod;
    
    @end
    
    #import "AutoMehtodModel.h"
    #import <objc/runtime.h>
    @implementation AutoMehtodModel
    @dynamic addAutoMethod;
    /**
      为addAutoMethod动态添加set和get方法
     **/
     +(BOOL)resolveInstanceMethod:(SEL)sel
    {
        NSString *addSelectorStr = NSStringFromSelector(sel);
        //v@:@是一种符合 涉及到https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html
        if ([addSelectorStr isEqualToString:@"setAddAutoMethod:"]) {
            class_addMethod(self, sel, (IMP)autoSetter, "v@:@");
        }else if ([addSelectorStr isEqualToString:@"addAutoMethod"]){
            class_addMethod(self, sel, (IMP)autoGet, "@@:");
        }
        return [super resolveInstanceMethod:sel];
    }
    
    void autoSetter(id self,SEL _cmd, id value){
        NSLog(@"set方法 === %@",value);
        
    }
    
    id autoGet(id self,SEL _cmd){
        return @"get方法";
    }
    
     AutoMehtodModel *model = [[AutoMehtodModel alloc]init];
        model.addAutoMethod   = @"动态方法";
        NSLog(@"%@",model.addAutoMethod);
    

    运行结果:

    2018-03-27 10:53:07.875514+0800 OC_Categroy[962:61285] set方法 === 动态方法
    2018-03-27 10:53:23.157687+0800 OC_Categroy[962:61285] get方法
    

    参考文献:http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/

    相关文章

      网友评论

          本文标题:Objective-C消息发送

          本文链接:https://www.haomeiwen.com/subject/tdizfftx.html