一、Objective-C之Runtime的概念

前一篇关于NSProxy代理涉及到的关于消息转发,把以前写的runtime文章从github上转移过来。一共三篇,似乎自己也忘记了一些runtime的细节,需要温故一下。

一、什么是Objc的Runtime?

Runtime是Objc语言的磐石,Objc语言得以运行,也是依靠runtime库的支持。

Objc语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。这种动态语言的优势在于:我们写代码时能够更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。这种特性意味着Objc不仅需要一个编译器,还需要一个运行时系统来执行编译的代码。对于Objc来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行,这个运行时系统即Objc Runtime。

Runtime基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。在这个库中,对象可以用C语言中的结构体表示,而方法可以用C函数来实现,再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,我们就可以在程序运行时创建,检查,修改类、对象和它们的方法了。runtime可以有效的帮助我们为程序增加很多动态的行为。

二、Runtime中的重要概念

先看一句最常见的方法调用代码:[receiver message];

刚开始学习Objc时,觉得上面的方法就是调用receiver对象的message方法。这样的理解也没错。更底层的原理应该是这样的:

向receiver对象发送消息,上面的代码会被编译器转成:

objc_msgSend(receiver, selector)

如果含有多个参数则是:

objc_msgSend(receiver, selector, arg1, arg2, ...)

如果消息的接收者receiver能够找到对应的selector,那就执行接收者receiver的这个message方法。否则消息将被转发,或临时动态的向接收者receiver添加这个selector的实现,或者直接崩溃。

至此,知道了编译阶段只是知道了向receiver对象发送了这样一个消息,至于消息能否被响应,需要等到运行时的具体情况决定。由此看出Objc的Runtime铸就了它动态语言的特性。

大部分情况下你就只管写你的Objc代码就行,runtime系统自动在幕后辛勤劳作着。消息的执行会使用到一些编译器为实现动态语言特性而创建的数据结构和函数,Objc中的类、方法和协议等在runtime中都由一些数据结构来定义。


三、梳理objc_msgSend

方法原型是:id objc_msgSend(id self, SEL op, ...)

id

id是指向类实例的结构体指针。定义如下:

typedef struct objc_object *id;

id这个结构体的定义本身就带了一个*号, 所以我们在使用其他NSObject类型的实例时需要在前面加上*, 而使用id时却不用。

接着,我们发现一个objc_object的定义,继续深入进去看下..

objc_object

objc_object其实是一个结构体,结构体里包含一个指向Class类的isa指针。根据isa指针就可以找到id实例所属的Class类了。

struct objc_object { Class isa; };

发现一个Class的定义,继续深入进去看下..

Class

Class是一个指针类型,指向了objc_class类型。

typedef struct objc_class *Class;

发现一个objc_class的定义,继续深入进去看下..

objc_class

这个objc_class可是一个重要大明星。也是runtime的重点。到这里,我们可以得出一个结论:每个id对象都有一个指向所属类的指针isa。通过该指针,对象可以找到它所属的类,也可以找到了其全部父类(这一句需要在学完objc_class结构体后得到,不过本篇不打算再说objc_class了,因为篇幅有限,重点需要另开一篇来学习总结)。

花开两朵各表一枝,这条线先挖到objc_class这里。然后回头继续看objc_msgSend的第二个参数SEL类型的op。

SEL

SEL其实是selector方法选择器的标示,换言之:SEL是用来标示selector的。

typedef struct objc_selector *SEL;

Objc在编译时,会依据每一个方法的名字、参数序列,生成一个唯一的整型标识(Int类型的地址),这个标识就是SEL。如下代码所示:

SEL sel = @selector(method);
NSLog(@"sel: %p", sel);//output:sel: 0x108dfbba3

两个类之间,不管它们是父类与子类的关系,还是之间没有这种关系,只要方法名相同,那么它的SEL就是一样的。每一个方法都对应着一个SEL。编译器会根据每个方法的方法名为那个方法生成唯一的SEL。这些SEL组成了一个Set集合,当我们在这个集合中查找某个方法时,只需要去找这个方法对应的SEL即可。而SEL本质是一个字符串,所以直接比较它们的地址即可。

当然,不同的类可以拥有相同的selector。不同类的实例对象执行相同的selector时,会在各自的方法列表中去根据selector去寻找自己对应的IMP。


objc_msgSend的调用过程(先理解其中的概念):

当向一个对象发送消息时,objc_msgSend方法根据对象的isa指针找到对象的类,然后在类的调度表(dispatch table)中查找selector。如果无法找到selector,objc_msgSend通过指向父类的指针找到父类,并在父类的调度表(dispatch table)中查找selector,以此类推直到NSObject类。一旦查找到selector,objc_msgSend方法根据调度表的内存地址调用该实现。 通过这种方式,message与方法的真正实现在执行阶段才绑定。

为了保证消息发送与执行的效率,系统会将全部selector和使用过的方法的内存地址缓存起来。每个类都有一个独立的缓存,缓存包含有当前类自己的 selector以及继承自父类的selector。查找调度表(dispatch table)前,消息发送系统首先检查receiver对象的缓存。

上面的描述如下图所示:

518904-20180709110214250-1349737610.png

至此初步认识了runtime,也初步了解了Objc的重要概念内容,比如id、SEL等。当然更深的东西,还要继续学习挖掘~~~

转载于:https://www.cnblogs.com/vokie/p/9282801.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/353351.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

matlab 替换指定的元素

方法二:a[12 4 5 6 0 12 0];bfind(a0);%将a中的0替换为8a(b)8方法一:a[12 4 5 6 0 12 0];blogical(a0);%将a中的0替换为8(%数值转逻辑,不知道为什么可以这样用)a(b)8注:1. 该替换函数不能替换NaN替换NaN可用…

[P1580] yyy loves Easter_Egg I

Link: P1580 传送门 Solution: 拿来练练字符串的读入: 1、$gets()$相当于$c$中的$getline()$,但返回值为指针!(无数据时为NULL) (都读入换行符,并将其舍弃) 2、$sscanf(起始指针,...…

matlab按某一列排序

bsortrows(a,2) %a 为要排序的矩阵。2表示按第几列进行排序,整数代表升序,负数代表降序。%将矩阵a按照第2列的升序排列,其他列不会作升序排列,而是将跟随着第2列 的变化,保持一一对应。bsortrows(a,-3) %将矩阵a按照…

python特殊函数__str__、__repr__和__len__

1.__str__ 首先介绍__str__ class Students(object):def __init__(self, *args):self.names args# def __str__(self): #   return str(self.names) # __repr__ __str__ ss Students(hyq,ysy) ss>>><__main__.Students at 0x2075a779828> 打印类对象…

MATLAB对矩阵中元素的访问

矩阵访问一律用()&#xff0c;元胞数组用{}a(i,j)%第i行第j列队元素a(:,j)%第j列的所有元素a(2:end,j)%第j列中第2行到最后一行的元素a(:,3:5)%第3〜5列的所有元素a(x)%第x个元素&#xff08;x为从最左边第1列开始编号&#xff0c;若a为4行5列&#xff0c;则a(10)a(2,3)&#x…

c函数scanf(),printf()等常用格式字符串

%d 短整形,一般占两个字节%u 无符号短整形%ld 长整形,一般占四个字节%c 字符型%s 字符串主要用在输入输出函数&#xff1a;scanf(),printf()里/a:蜂鸣&#xff0c;响铃 /b:回退&#xff1a;向后退一格 /f:换页 /n:换行&#xff0c;光标到下行行首 /r:回车&#xff0c…

jsf服务_使用JSF的面向服务的UI

jsf服务在大型软件开发项目中&#xff0c;面向服务的体系结构非常常见&#xff0c;因为它提供了可供不同团队或部门使用的功能接口。 创建用户界面时&#xff0c;应应用相同的原理。 对于具有开票部门和客户管理部门等的大型公司&#xff0c;组织结构图可能如下所示&#xff1a…

MATLAB矩阵对称旋转

fliplr(a) 矩阵左右翻转 flipud(a) 矩阵上下翻转 rot90(a)矩阵逆时针旋转90度&#xff08;把你的头顺时针旋转90看原数就可以知道结果了,^-^&#xff09;rot90(a,k) k参数定义为逆时针旋转90*k度。

English trip -- Phonics 3 元音字母e

xu言&#xff1a; 额...今天给我上自然拼读的maple老师 - . -和上次给我上第二集自然拼读的是同一个老师。突然考了考我上次学的内容~感觉大脑一片空白。看来review不能光说而不下苦功夫啊... 元音 vowel 长音 /i:/ be me we he chinese ee meet bee see sleep queen …

生成随机测试数据的文件的程序

例如以下简单的AB问题&#xff1a; 样例 输入&#xff1a; 1 2 输出&#xff1a; 3 答案&#xff1a; #include <stdio.h> int main() {int a,b;while(scanf("%d%d",&a,&b)!EOF){printf("%d\n",ab);}return 0; }机器的测试&#xff1a;…

ANTLR和Jetbrains MPS:解析文件并以树符号显示AST

Itemis再次这样做&#xff1a;他们刚刚为Jetbrains MPS发布了一个非常酷的新插件。 这允许定义新的树编辑器。 他们看起来像这样&#xff1a; 在这篇文章中&#xff0c;我们将看到&#xff1a; 如何在MPS中使用ANTLR解析器 如何使用树符号表示已解析的AST 特别是&#xf…

MATLAB判断矩阵相等

1. AB;%得到的是一个矩阵&#xff0c;对应值相等则返回1&#xff0c;否则返回02. ~norm(A-B);%若AB则A-B全零&#xff0c;norm(A-B)的结果为0&#xff0c;否则为1&#xff1b;其中norm为范数3. ~sum(sum(abs(A-B)));%原理和2相同&#xff0c;但是计算速度要快于2数倍 4. isequ…

python全栈-Day 1

Python是一种动态强类型解释型语言 1、Python历史 Python2与Python3的区别&#xff1a; Python2&#xff1a; 源码不标准&#xff0c;混乱&#xff0c;重复代码多 默认编码方式是ASCII码&#xff0c;因此需要在文件的首行 #-*- encoding:utf-8 -*- Python3&#xff1a; 统一标准…

KMP字符串模式匹配详解

刚看到位兄弟也贴了份KMP算法说明&#xff0c;但本人觉得说的不是很详细&#xff0c;当初我在看这个算法的时候也看的头晕昏昏的&#xff0c;我贴的这份也是网上找的。且听详细分解&#xff1a;KMP字符串模式匹配详解 来自CSDN A_B_C_ABC 网友 KMP字符串模式匹配通俗点说…

Matlab找矩阵中最大最小值的位置

1. ind find(Amin(min(A)));2. [row,column]find(Amin(min(A)));

ASP.NET Core IdentityServer4 新手上路

OAuth2.0资料 今天看到一篇博主写了该系列文章,贴图和过程都比较详细,俗话说实践是检验真理的唯一标准&#xff08;如果是按照参考文章复制粘贴,应该不会出现踩坑&#xff0c;但是我喜欢自己手动敲一遍&#xff09;&#xff0c;发现几个坑&#xff0c;因而总结下经验&#xff0…

MATLAB矩阵复制数据

如果想让矩阵A(m,n)的数据的每一行复制b遍&#xff0c;组成一个m*b行的大矩阵&#xff0c;可以用B A(reshape(ones(b,1)*(1:m),m*b,1),:);

博弈知识汇总

以下是我从网上收集的关于组合博弈的资料汇总&#xff1a; 有一种很有意思的游戏&#xff0c;就是有物体若干堆&#xff0c;可以是火柴棍或是围棋子等等均可。两个 人轮流从堆中取物体若干&#xff0c;规定最后取光物体者取胜。这是我国民间很古老的一个游戏 &#xff0c;别看这…

主成分分析和因子分析区别与联系

主成分分析可以简单的总结成一句话&#xff1a;数据的压缩和解释。常被用来寻找判断某种事物或现象的综合指标&#xff0c;并且给综合指标所包含的信息以适当的解释。在实际的应用过程中&#xff0c;主成分分析常被用作达到目的的中间手段&#xff0c;而非完全的一种分析方法。…