要说清楚消息这个话题,我们必须先来了解三个概念 Class, SEL, IMP,它们在 objc/objc.h 中定义:

typedef struct objc_class *Class; 
typedef struct objc_object {
  Class isa;
} *id; typedef struct objc_selector *SEL;
typedef id (*IMP)(id, SEL, ...);
  • Class 的含义 

Class 被定义为一个指向 objc_class 的结构体指针,这个结构体表示每一个类的类结构。而 objc_class 在 objc/objc_class.h 中定义如下:

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; /*协议链表*/
};
NSObject 的 class 方法就返回这样一个指向其类结构的指针。每一个类实例对象的第一个实例变量是一个指向该对象的类结构的指针,叫做isa.

通过该指针,对象可以访问它对应的类以及相应的父类。如图一 所示:

如图一所示,圆形所代表的实例对象的第一个实例变量为 isa,它指向该类的类结构 The object’s class。 而该类结构有一个指向其父类类结构的指针 superclass, 以及自身消息名称(selector)/实现地址(address) 的方法链表。

  • 方法的含义:

注意这里所说的方法链表里面存储的是 Method 类型的。图一中 selector 就是指 Method 的

SEL, address 就是指 Method 的 IMP。 Method 在头文件 objc_class.h 中定义如下:

typedef struct objc_method *Method;
typedef struct objc_ method
{
SEL method_name;//表示该方法的名称 
char *method_types;//该方法参数的类型
IMP method_imp; //指向该方法的具体实现的函数指针 
};
  • SEL 的含义:

在前面我们看到方法选标 SEL 的定义为:
typedef struct objc_selector *SEL;
它是一个指向 objc_selector 指针,表示方法的名字/签名。

-(NSInteger)maxIn:(NSInteger)a theOther:(NSInteger)b
{
return (a > b) ? a : b;
} NSLog(@"SEL=%s", @selector(maxIn:theOther:));
输出:SEL=maxIn:theOther:
不同的类可以拥有相同的 selector,这个没有问题,因为不同类的实例对象 performSelector 相同的 selector 时,会在各自的消息选标(selector)/实现地址(address) 方法链表中根据 selector 去查找具体的 方法实现 IMP, 然后用这个方法实现去执行具体的实现代码。这是一个动态绑定的过程,在编译的时候, 我们不知道最终会执行哪一些代码,只有在执行的时候,通过 selector 去查询,我们才能确定具体的执行代码。 
  • IMP 的含义:

在前面我们也看到 IMP 的定义为: typedef id (*IMP)(id, SEL, ...);

根据前面 id 的定义,我们知道 id 是一个指向 objc_object 结构体的指针,该结构体只有一个成员 isa,所 以任何继承自 NSObject 的类对象都可以用 id 来指代,因为 NSObject 的第一个成员实例就是 isa。

IMP 是一个函数指针,这个被指向的函数包含一个接收消息的对象id(self 指针), 调用方法的选标 SEL (方法名),以及不定个数的方法参数,并返回一个 id。

NSObject 类中的 methodForSelector:方法就是这样一个获取指向方法实现 IMP 的指针, methodForSelector:返回的指针和赋值的变量类型必须完全一致,包括方法的参数类型和返回值类型。

下面的例子展示了怎么使用指针来调用 setFilled:的方法实现:

void (*setter)(id, SEL, BOOL);
int i; setter = (void(*)(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)]; for (i = ; i < ; i++)
setter(targetList[i], @selector(setFilled:), YES);
使用 methodForSelector:来避免动态绑定将减少大部分消息的开销,但是这只有在指定的消息被重复发 送很多次时才有意义 
注意,methodForSelector:是 Cocoa 运行时系统的

OC之消息基本概念的更多相关文章

  1. OC中协议的概念以及用法

    OC中协议的概念以及用法,协议也是OC中的一个重点,Foundation框架以及我们后面在写代码都会用到. OC中的协议就是相当于Java中的接口(抽象类),只不过OC中的名字更形象点,因为我们在学习 ...

  2. MQ(1)---消息队列概念和使用场景

    消息队列概念和使用场景 声明:本文转自:MQ入门总结(一)消息队列概念和使用场景 写的很好,都不用自己在整理了,非常感谢该作者的用心. 一.什么是消息队列 消息即是信息的载体.为了让消息发送者和消息接 ...

  3. [Pulsar系列] 10分钟学会Pulsar消息系统概念

    Apache Pulsar Pulsar是一个支持多租户的.高性能的服务与服务之间消息通讯的解决方案,最初由雅虎开发,现在由Apache软件基金会管理. Pulsar的主要特性如下: Pulsar实例 ...

  4. OC的消息机制简单介绍

    在OC的消息机制中主要分为三个阶段,分别为: 1.消息发送阶段:从类以及父类的方法缓存列表和方法列表查找方法. 2.动态解析阶段:在消息发送阶段没有找到方法,则会进入这个阶段,负责动态添加方法实现. ...

  5. Objective-C 利用OC的消息机制,使用Method Swizzling进行方法修改

    功能:修改父类不可修改函数方法,函数方法交换 应用场景:假如我们使用的他人提供一个的framework,.m已被打包成二进制.a无法修改源码,只留下.h头文件,那假如代码中某个函数出现了问题可以通过这 ...

  6. OC中对象拷贝概念

    OC中的对象拷贝概念,这个对于面向对象语言中都会有这种的问题,只是不同的语言有不同的解决方式:C++中有拷贝构造函数,Java中需要实现Cloneable接口,在clone方法中进行操作.但是不过OC ...

  7. JavaEE Tutorials (16) - Java消息服务概念

    16.1JMS API概述198 16.1.1什么是消息传送198 16.1.2什么是JMS API199 16.1.3何时使用JMS API199 16.1.4Java EE平台如何使用JMS AP ...

  8. 消息队列 概念 配合SpringBoot使用Demo

    转http://www.jianshu.com/p/048e954dab40 概念: 分布式消息队列 ‘分布式消息队列’包含两个概念 一是‘消息队列’,二是‘分布式’ 那么就先看下消息队列的概念,和为 ...

  9. iOS 面试题:OC标题的基本概念&lt;延续&gt;

    第一,如何确定一个方法方法名称 删除减号,加,删除返回值,删除参数类型,删除参数,剩下的就是的方法名 秒,id,能够用assign,copy,retain,依据须要使用 第三,autorelease ...

随机推荐

  1. IIS错误解决办法(HTTP Error 500.19 - Internal Server Error)

    window10 切换登陆用户,VS2015的IIS Express 调试代码报HTTP Error 500.19 - Internal Server Error 错误,无法读取配置文件解决办法. I ...

  2. DB2的基础指令 学习笔记

    =======DB2基础指令======= 1.打开数据库db2 connect to 数据库名;2.查看数据库中有哪些表db2 list tables ;3.查看数据库中的表结构db2 descri ...

  3. ASP.NET用户控件操作ASPX页面

    定义一个不含数据的事件处理方法 用户控件 public event EventHandler Click; protected void Button1_Click(object sender, Ev ...

  4. jvm原理及调优

    一.java内存管理及垃圾回收 jvm内存组成结构 jvm栈由堆.栈.本地方法栈.方法区等部分组成,结构图如下所示: (1)堆 所有通过new创建的对象的内存都在堆中分配,堆的大小可以通过-Xmx和- ...

  5. Excel 复制Sql查询结果错位

    SELECT TOP 30000 REPLACE(REPLACE(T1.ReceiverName,CHAR(10),' '),CHAR(13),' ') AS ReceiverName, REPLAC ...

  6. foreach绑定

    目的 foreach可以将一个数组中的实体循环的进行绑定.这在将一个list显示成table时非常有用. 假设数组是observable的,当在绑定后做了add, remove,或者重新排序后,绑定会 ...

  7. Math.round(),Math.ceil(),Math.floor()的区别

    1.Math.round():根据"round"的字面意思"附近.周围",可以猜测该函数是求一个附近的整数,看下面几个例子就明白. 小数点后第一位<5 正 ...

  8. HDU 4451 Dressing

    HDU 4451 Dressing 题目链接http://acm.split.hdu.edu.cn/showproblem.php?pid=4451 Description Wangpeng has ...

  9. 简单的socket方法

    void sockfunc() { WSADATA Ws; WSAStartup(MAKEWORD(,), &Ws); SOCKET hs = socket(AF_INET, SOCK_STR ...

  10. maven GroupId 和ArtifactId的含义

    GroupID是项目组织唯一的标识符,实际对应Java的包的结构,是main目录里java的目录结构. ArtifactID就是项目的唯一的标识符,实际对应项目的名称,就是项目根目录的名称.