一、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,一经查实,立即删除!

相关文章

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

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

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

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

KMP字符串模式匹配详解

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

ASP.NET Core IdentityServer4 新手上路

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

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

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

luogu P1519 穿越栅栏 Overfencing

题目描述 描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口。更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找到一条走出迷宫的路。给定迷…

css实现简单的告警提示动画效果

需求&#xff1a;css实现简单的告警提示动画效果&#xff0c;当接收到实时信息的时候&#xff0c;页面弹出告警信息的动画效果<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>css实现告警提示动画</…

程序员的八个级别

2009年4月6日 陈皓 在面试时&#xff0c;你可能会被经常问到“在未来5年&#xff0c;你想干什么&#xff1f;”&#xff0c;这可能是一个比较难回答的问题。在中国&#xff0c;答案一般可能会是Team leader&#xff0c;Manager&#xff0c;或是Architect&#xff0c;Specialist…

一个具有Spring Boot,Spring Security和Stormpath的简单Web应用程序-15分钟

建筑物身份管理&#xff0c;包括身份验证和授权&#xff1f; 尝试Stormpath&#xff01; 我们的REST API和强大的Java SDK支持可以消除您的安全风险&#xff0c;并且可以在几分钟内实现。 注册 &#xff0c;再也不会建立auth了&#xff01; 更新 &#xff1a;我们最近发布了对…

javafx2_JavaFX 2 GameTutorial第5部分

javafx2介绍 这是与JavaFX 2 Game Tutorial相关的六部分系列的第五部分。 我知道自从我写关于游戏的博客以来已经有很长时间了&#xff0c;但希望您仍然与我在一起。 如果您想回顾一下&#xff0c;请阅读第1部分 &#xff0c; 第2 部分 &#xff0c; 第3 部分和第4 部分 &#…

史上最简单的SpringCloud教程 | 第二篇: 服务消费者(rest+ribbon)(Finchley版本)

转载请标明出处&#xff1a; 原文首发于&#xff1a;https://www.fangzhipeng.com/springcloud/2018/08/30/sc-f2-ribbon/ 本文出自方志朋的博客 在上一篇文章&#xff0c;讲了服务的注册和发现。在微服务架构中&#xff0c;业务都会被拆分成一个独立的服务&#xff0c;服务与服…

忽略已检查的异常,所有出色的开发人员都在这样做–基于600,000个Java项目

Github和Sourceforge上超过600,000个Java项目中的异常处理概述 Java是使用检查异常的少数语言之一。 它们在编译时强制执行&#xff0c;并且需要某种处理。 但是……实践中会发生什么&#xff1f; 大多数开发人员实际上处理任何事情吗&#xff1f; 以及他们如何做到的&#xf…

使用Boxfuse轻松在云中运行Spring Boot应用程序

几天前&#xff0c;我开始构建一个将使用REST API检索和存储数据的iOS应用。 该REST API将是我也必须构建的服务器应用程序。 由于我熟悉Java和Spring &#xff0c;因此决定使用Spring Boot作为框架。 为了能够在我的iPhone上使用它&#xff0c;如果我可以在服务器而不是我自己…

numpy的使用数组的创建2

随机创建了长度为十的数组 获得十以类的随机整数 快速获取数组2乘3维的数组 生成20个1到10之间的数组 通过reshape 将这些数变成二位数组 shape这个方法可以查看数组中的元素是几行几列的 转载于:https://www.cnblogs.com/chenligeng/p/9315339.html

Tabs vs Spaces:如何在Google,Twitter,Mozilla和Pied Piper上编写Java

流行的Java代码样式中最有趣的亮点是什么&#xff1f; 尽管上面有暗示性的形象&#xff0c;我们也不想发动任何不必要的圣战。 当归结为编码样式时&#xff0c;大多数选择都是相当随意的&#xff0c;并取决于个人喜好。 是的&#xff0c;即使在编辑器之间制表符宽度改变了&…

ES group分组聚合的坑

参考链接&#xff1a;https://blog.csdn.net/u010454030/article/details/71762838 ES group分组聚合的坑 原来知道Elasticsearch在分组聚合时有一些坑但没有细究&#xff0c;今天又看了遍顺便做个笔记和大家分享一下。 我们都知道Elasticsearch是一个分布式的搜索引擎&#xf…

字典树 ZOJ1109 HDU1251 PKU1204 HDU1075

又称单词查找树&#xff0c;Trie树&#xff0c;是一种树形结构&#xff0c;是一种哈希树的变种。典型应用是用于统计&#xff0c;排序和保存大量的字符串&#xff08;但不仅限于字符串&#xff09;&#xff0c;所以经常被搜索引擎系统用于文本词频统计。它的优点是&#xff1a;…

Codeforces Round #498 (Div. 3) F. Xor-Paths

题目链接&#xff1a;F. Xor-Paths 题解&#xff1a;从起点和终点双向搜索在中间相遇时更新答案 1 #include<bits/stdc.h>2 #include<set>3 #include<cstdio>4 #include<iomanip>5 #include<iostream>6 #include<string>7 #include<cst…

创建健壮的微服务架构所涉及的组件

在本文中&#xff0c;我们将简要学习构建强大的微服务应用程序所需的各种软件组件。 在简要了解每个架构组件之前&#xff0c;我们将陈述设计微服务架构时出现的一般查询。 1.微服务架构组件 每当我们创建微服务应用程序时&#xff0c;我们都会想到以下问题 我们将如何注册微…