objective-c下的消息机制

简介: l   消息机制:   Objective-c下调用函数并不是采用的想C语言中的函数调用机制而是使用的一种消息传递的机制。下文将讨论这两种协议之间的区别。   传统的函数调用机制是在程序编译的阶段就已经将子函数的引用地址编译进了执行代码,所以当编译完成之后,函数名指向的就是函数的入口地址,而调用函数将直接导向至函数的入口地址,从而直接开始执行函数。   而Objective-c采用的

l   消息机制:

  Objective-c下调用函数并不是采用的想C语言中的函数调用机制而是使用的一种消息传递的机制。下文将讨论这两种协议之间的区别。

  传统的函数调用机制是在程序编译的阶段就已经将子函数的引用地址编译进了执行代码,所以当编译完成之后,函数名指向的就是函数的入口地址,而调用函数将直接导向至函数的入口地址,从而直接开始执行函数。

  而Objective-c采用的是一种消息传递机制,即以消息的形式将要执行的函数传递给对应的对象,此时对象在自己的方法列表中查找对应的函数,如果找到了就执行,如果没有就在父类中查找。在这样的机制下,程序在编译的时候,要执行哪个函数其实是没有确定的,这也就是所谓的动态调用。其具体的操作如下。

  在objective-c下,当编译器编译到一个函数调用的时候,编译器会调用一个obj_msgSend函数:

id objc_msgSend(id theReceiver, SELtheSelector, ...)

  theReceiver是接收该消息的对象,SELtheSelector则是要调用函数的选择器(选择器的具体介绍详见下文),后面还可以跟多个函数传入的参数。在程序执行的时候,theReceiver对象会在自己的方法列表中找寻SELtheSelector指向的函数,如果没有找到就继续查找其父类,找到之后,执行该函数。以上就是objective-c下的消息机制。可以看出,在编译之后,具体要调用哪些函数并没有确定。

l   选择器:

  在消息传递函数obj_msgSend函数中有一个选择器,那么选择器是什么呢?其作用相当于函数指针,现在我看到的大多说用法都是在调用某些函数需要传递一个函数指针 参数时,使用@selector。它会在当前类里面查找selector后面所跟的函数,返回一个SEL类型的值。Objective-C在编译的时候,会根据方法的名字(包括参数序列),生成一个用 来区分这个方法的唯一的一个ID,这个ID就是SEL类型的。我们需要注意的是,只要方法的名字(包括参数序列)相同,那么它们的ID都是相同的。就是说,不管是超类还是子类,不管是有没有超类和子类的关系,只要名字相同那么ID就是一样的。除了函数名字和ID,编译器当然还要把方法编译成为机器可以执行的代码。其实简单地理解可以将SEL类型理解为一个char*,因为它的确可以用char*的形式打印出来:

SEL hah=@selector(message);
NSLog(@"%s",(char*)hah);

  SEL类型的声明有多种方法,除了SEL=@selector(方法名)这种方式以外,还有另一种方法:

SEL 变量名 = NSSelectorFromString(方法名字的字符串);

而方法:

NSString *变量名 = NSStringFromSelector(SEL参数);

可以获得选择器对应方法的名称。

  在Objective-c下,方法的定义如下:

 typedef struct objc_method *Method;
 typedef struct objc_ method {
    SEL method_name;//方法名称
    char *method_types;//方法参数类型
    IMP method_imp;//方法实现的函数指针
 };

其中的method_imp参数就是指向函数的指针,其定义如下:

typedef id (*IMP)(id, SEL, ...);
而id实际只是一个Class对象,其名字位isa,每一个NSObject对象都有一个isa成员:

 typedef struct objc_object {
    Class isa;
 } *id;

关于Class类,其定义如下:

  struct objc_class {
    struct objc_class super_class;  /*父类*/
    const char *name;                 /*类名字*/
    long version;                   /*版本信息*/
    long info;                        /*类信息*/
    long instance_size;               /*实例大小*/
    struct objc_ivar_list *ivars;     /*实例参数链表*/
    struct objc_method_list **methodLists;  /*方法链表*/
    struct objc_cache *cache;               /*方法缓存*/
    struct objc_protocol_list *protocols;   /*协议链表*/
 };

  到这里一切都明了了,这个IMP对象实际上指向的是函数的执行地址,同时还传入了一个接收对象的id(self指针)以及对应SEL和对应的参数。同时还会返回一个id。

l   实例:

  也许你会问,这样的机制相对于以前的函数调用机制来说有什么优势呢?在我看来,最重要的就是其实现了函数的动态调用,我们不需要在一开始编写代码的时候就决定在某个特定的时候需要执行什么函数。而是可以在之后的某个时候再决定要执行的函数。看下面这个实例:

        NSMutableArray *list2=[NSMutableArray arrayWithObjects:@"four",@"five",@"six",nil];
        SEL sel=NSSelectorFromString(@"count");
         NSLog(@"items of list2:%@   \n it has %lu elements",list2,[list2 performSelector:sel]);

只需要在一个特定的时候传入函数的名称,我们就可以动态调用函数。这就是该机制的优势。




相关文章
|
iOS开发 开发者
动态的Objective-C——关于消息机制与运行时的探讨(四)
动态的Objective-C——关于消息机制与运行时的探讨
118 0
|
iOS开发
动态的Objective-C——关于消息机制与运行时的探讨(三)
动态的Objective-C——关于消息机制与运行时的探讨
194 0
动态的Objective-C——关于消息机制与运行时的探讨(三)
|
iOS开发 开发者
动态的Objective-C——关于消息机制与运行时的探讨(二)
动态的Objective-C——关于消息机制与运行时的探讨
156 0
动态的Objective-C——关于消息机制与运行时的探讨(二)
|
缓存 自然语言处理 IDE
动态的Objective-C——关于消息机制与运行时的探讨(一)
动态的Objective-C——关于消息机制与运行时的探讨
150 0
动态的Objective-C——关于消息机制与运行时的探讨(一)
|
存储 C语言 iOS开发
(转载)Objective-C总Runtime的那点事儿(一)消息机制
原文地址:http://www.cocoachina.com/ios/20141018/9960.html 找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题。
967 0
|
3月前
|
安全 编译器 Swift
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
IOS开发基础知识: 对比 Swift 和 Objective-C 的优缺点。
89 2
|
3月前
|
安全 JavaScript 前端开发
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
IOS开发基础知识:介绍一下 Swift 和 Objective-C,它们之间有什么区别?
65 0
|
机器学习/深度学习 API iOS开发
【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词(一)
【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词(一)
140 0
|
存储 自然语言处理 Java
【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词(二)
【IOS 开发】Objective-C Foundation 框架 -- 字符串 | 日期 | 对象复制 | NSArray | NSSet | NSDictionary | 谓词(二)
218 0
|
Java iOS开发
【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态(二)
【iOS 开发】Objective - C 面向对象 - 方法 | 成员变量 | 隐藏封装 | KVC | KVO | 初始化 | 多态(二)
116 0