ios学习路线—Objective-C(Runtime消息机制)

RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 )。编译完成之后直接顺序执行,无任何二义性。OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。

那OC是怎么实现动态调用的呢?下面我们来看看OC通过发送消息来达到动态调用的秘密。假如在OC中写了这样的一个代码:

[obj makeText];

其中obj是一个对象,makeText是一个函数名称。对于这样一个简单的调用。在编译时RunTime会将上述代码转化成

objc_msgSend(obj,@selector(makeText));

首先我们来看看obj这个对象,iOS中的obj都继承于NSObject。

@interface NSObject <nsobject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}

在NSObjcet中存在一个Class的isa指针。然后我们看看Class:

typedef struct objc_class *Class;
struct objc_class {
  Class isa; // 指向metaclass

  Class super_class ;       // 指向其父类
  const char *name ;        // 类名
  long version ;         // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取
  long info;            // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法;
  long instance_size ;       // 该类的实例变量大小(包括从父类继承下来的实例变量);
  struct objc_ivar_list *ivars; // 用于存储每个成员变量的地址
  struct objc_method_list **methodLists ; // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法;
  struct objc_cache *cache;  // 指向最近使用的方法的指针,用于提升效率;
  struct objc_protocol_list *protocols; // 存储该类遵守的协议
}

我们可以看到,对于一个Class类中,存在很多东西,下面我来一一解释一下: 
Class isa:指向metaclass,也就是静态的Class。一般一个Obj对象中的isa会指向普通的Class,这个Class中存储普通成员变量和对 象方法(“-”开头的方法),普通Class中的isa指针指向静态Class,静态Class中存储static类型成员变量和类方法(“+”开头的方 法)。

Class super_class:指向父类,如果这个类是根类,则为NULL。 
下面一张图片很好的描述了类和对象的继承关系: 
 
注意:所有metaclass中isa指针都指向根metaclass。而根metaclass则指向自身。Root metaclass是通过继承Root class产生的。与root class结构体成员一致,也就是前面提到的结构。不同的是Root metaclass的isa指针指向自身。

Class类中其他的成员这里就先不做过多解释了,下面我们来看看:(下面文字要深入理解

@selector (makeText):这是一个SEL方法选择器。SEL其主要作用是快速的通过方法名字(makeText)查找到对应方法的函数指针,然后调用其函 数。SEL其本身是一个Int类型的一个地址,地址中存放着方法的名字。对于一个类中。每一个方法对应着一个SEL。所以iOS类中不能存在2个名称相同 的方法,即使参数类型不同,因为SEL是根据方法名字生成的,相同的方法名称只能对应一个SEL。

下面我们就来看看具体消息发送之后是怎么来动态查找对应的方法的。

首先,编译器将代码[obj makeText];转化为objc_msgSend(obj, @selector (makeText));,在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。在Class中先去cache中 通过SEL查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若 cache中未找到。再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加 入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。

原文地址:https://www.cnblogs.com/jiuyi/p/10142013.html

时间: 2024-11-05 17:30:52

ios学习路线—Objective-C(Runtime消息机制)的相关文章

iOS开发——iOS学习路线

iOS学习路线 一:自学初步学习路线 二:完整学习路线

ios学习路线_OC基础语法

OC是面向对象的语言,同java,python等等一样. OC中的变量类命名同其他对象语言基本类似,写法遵循驼峰法则 一般命名用到的是下划线,字母,开头字符非数字,网上很多有说也可以$符号,其实命名中基本不会用到这个 OC里面的关键字也不多,如图: OC中分基本数据类型和指针类型(即指对象类型) 那么一些基本类型的范围值和写法,这里不一一说,网上太多了,随便百度下 下面废话也不多说,直接给个网上的ppt说明吧 其实写过面向对象语言的朋友,基本上这块so easy 这里可以下载oc的基础部分 io

iOS:runtime消息机制

最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎必问,例 如:RunLoop,Block,内存管理等.其他的问题如果有机会我会在其他文章中介绍.本篇文章主要介绍RunTime. RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何二义性.OC的函数调用成为消息发送

Object-c runtime消息机制

RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何二义性.OC的函数调用成为消息发送.属于动态调用过程.在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错.而C语言在编译阶段就会报错).只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用. 那OC是怎么实现动态调

iOS 学习路线

1.工作时,需要什么学习什么,学习一个新东西时,多看官门文档,iOS Developer Library. 2.开始每天的工作总结,开始看objc中国,一周一大节. 3.回来时按照iOS开发路线学习,练习完c plus 函数,数组,指针事例. 4.周六做总结,对一周不合理的地方作出适当调整. 5.回到住的地方实行比例时学习,20%时间看书作总结(读书总结)看小狗钱钱,40%学习C语言,10%英语(10个单词),10%财经(可汗学院教程),10%锻炼,10%休息(按照蕃茄时间).

RunTime(消息机制) + RunTime(消息转发)

一.消息机制 1.在viewDidLoad中直接用 performSelector:@selector(doSomething) 来调用doSomething方法时,会发现找不到这个方法而奔溃.此时,我们可以在resolveInsantanceMethod:(SEL)see 方法中获取这个所有在运行时阶段的方法,在这个方法中只需要判断一下,将这个方法获取,并且运用Runtime 的 class_addMethod 的方法来将方法和响应函数绑定,进而达到为某一个类添加方法的目的. - (void)

【转载】Objective-C runtime 消息机制

在Objective-C中,message与方法的真正实现是在执行阶段绑定的,而非编译阶段.编译器会将消息发送转换成对objc_msgSend方法的调用.objc_msgSend方法含两个必要参数:receiver.方法名(即:selector),如:[receiver message]; 将被转换为:objc_msgSend(receiver, selector);objc_msgSend方法也能hold住message的参数,如:objc_msgSend(receiver, selector

ios学习路线—Objective-C(属性修饰符)

readonly: 此标记说明属性是只读的,默认的标记是读写,如果你指定了只读,在@implementation中只需要一个读取器.或者如果你使用@synthesize关键字,也是有读取器方法被解析.而且如果你试图使用点操作符为属性赋值,你将得到一个编译错误. readwrite: 此标记说明属性会被当成读写的,这也是默认属性.设置器和读取器都需要在@implementation中实现.如果使用@synthesize关键字,读取器和设置器都会被解析. nonatomic: 非原子性访问,对属性赋

ios学习路线—Objective-C(堆(heap)和栈(stack))

Objective-C的对象在内存中是以堆的方式分配空间的,并且堆内存是由你释放的,即release 栈由编译器管理自动释放的,在方法中(函数体)定义的变量通常是在栈内,因此如果你的变量要跨函数的话就需要将其定义为成员变量. 1.栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量等值.其操作方式类似于数据结构中的栈. 2.堆区(heap):一般由程序员分配释放,若程序员不释放,则可能会引起内存泄漏.注堆和数据结构中的堆栈不一样,其类是与链表. 操作系统iOS 中应用程序使用的计