IOS -运行时 (消息传递 )

iOS——消息传递和消息转发机制 首先我们了解了什么是消息发送,明白了OC语言中所有对象的方法调用都是消息发送。其次我们知道了消息发送是SEL-IMP的查找过程调用resolveInstanceMethod或者resolveClassMethod作为动态解析方法给本类一个补救的方法去动态添加没有实现的方法的实现调用forwardingTargetForSelector让别的对象去执行这个函数(消息转发)forwardInvocation灵活的将目标函数以其他形式执行(我们的这个完整的消息转发的实现可以很简单https。... 阅读详情

一 函数调用概述


     Objective-C不支持多重继承(同Java和Smalltalk),而C++语言支持多重继承。 Objective-C是动态绑定,它的类库比C++要容易操作。Objective-C在运行时可以允许根据字符串名字来访问方法和类,还可以动态连接和添加类。 C++ 跟从面向对象编程里的Simula 67(一种早期OO语言)学派,而Objecive-C属于Smalltalk学派,Simula 67学派更安全,因为大部分错误可以在编译时查出。 在C++里,对象的静态类型决定你是否可以发送消息给它,而对Objective-C来说,由动态类型来决定。


     Objective-C比C++ 更强调类型的动态性,虽然牺牲了一些执行性能,但由于模型清晰,而牺牲的这些性能可以在今天由更先进的编译技术来弥补。


二 消息的产生

     在Objective-c中消息一直到运行时才能绑定到对应的函数:
     [reveiver message];
     编译器在处理时会将上面的表达式处理称下面这种形式:
     objc_msgSend(receiver,selector);
     如果方法有多个参数的时候会处理成下面这种形式:
     objc_msgSend(receiver,selector,arg1,arg2,…….); 
     现在我们知道了在Objective-c中函数调用都会被编译器进行预处理,调用obj_msgSend函数进行消息的发送。这里需要弄明白的selector是什么东东?receiver是怎么样来调用指定的函数的,它在背后是怎样实现的?下面将逐一解释。

三 类对象中与消息有关的结构
首先看一下与消息传递有关的几个数据结构和数据类型。
  1. struct objc_method_list **methodLists
  在上一节中知道在类对象objc_class中有一个结构体 struct objc_method_list **methodLists ,它其实是方法的映射表。
  下面是objc_method_list的结构
 struct objc_method_list {
    struct objc_method_list *obsolete                        
    int method_count                                         
    struct objc_method method_list[1]                       
 }


在objc_method_list中包含一个objc_method结构体
下面是objc_method的结构体
struct objc_method {   
       SEL  method_name 
char *method_types 
       IMP method_imp 
}  

   objc_method用来代表一个方法,其包含一个方法 SEL – 表示该方法的名称,一个types – 表示该方法的参数,一个 IMP - 指向该方法的具体实现的函数指针。 对于每个参数下面将具体说明。
     
      函数映射表的大致情况如下图所示



  2.SEL (An opaque type that represents a method selector)

    被定义为 typedef struct objc_selector *SEL 
  文档中并没有透露objc_selector是什么东西,但提供了@selector指令来生成:


    Objective-C在编译的时候,会根据方法的名字,生成 一个用来区分这个方法唯一的ID,这个ID就是 SEL类型的。(A selector is the name used to select a method to execute for an object, or the unique identifier that replaces the name when the source code is compiled. A selector by itself doesn’t do anything. It simply identifies a method. The only thing that makes the selector method name different from a plain string is that the compiler makes sure that selectors are unique. )只要方法的名字(包括参数序列)相同,那么它们的 ID都是相同的。就是 说,不管是超类还是子类,不管是有没有超类和子类的关系,只要名字相同那么ID就是一样的。

          说的通俗点,SEL就是一个函数标识,该标识是编译器根据其函数声明原型生成的。那如果两个不同的类如果有相同的函数声明的话会生产相同的ID(Objective-c 是不支持在类内函数重载的),那怎样进行区分呢?请继续往下看!

  3.IMP ( A pointer to the function of a method implementation)

      被定义为typedef id (*IMP)(id, SEL, ...)   
     IMP是一个函数指针,它指向的函数第一个参数实例变量的地址,即接受消息的对象的地址(receiver),第二个参数是SEL要调用的方法、第三个蚕食是函数参数,它是一个不定参数,函数的返回值为id类型。
     IMP 是消息最终调用的执行代码,该是方法是真正的实现代码 。我们可以像在C语言里面一样使用这个函数指针。

     - (void) viewDidLoad
     {
         [super viewDidLoad];
         //声明一个函数指针
         void (*MyPrint)(id,SEL,NSString*);  
         MyPrint = ( void (*)(id,SEL,NSString*) )[self methodForSelector:@selector(Print:)];    
         MyPrint(self,@selector(Print:),@"Hello World");
     }
     
     - (void) Print:(NSString*) str
     {
         NSLog(@"%@",str);     
     }

    - (IMP)methodForSelector:(SEL)aSelector 函数的作用是通过SEL生成的ID来查找和定位函数的实现地址。
    MyPrint(self,@selector(Print:),@"Hello World”); 调用MyPrint函数指针所指向的函数,参数分别为receiver,SEL和要传递给函数的参数。
      
   通过上面的例子,我们明白了通过函数的第一个参数receiver可以区分不同类的函数声明相同的函数。


四 Objective-c消息传递

通过上面的一层层剖析和前一节有关类对象的讲解,可能你大概明白了Objective-c中消息的传递方式了。
    首先,编译器根据函数声明生成一个唯一函数ID,每个实例变量的第一个成员是isa,它指向类对象,在类对象中保存有该类所拥有的方法列表,通过生成的的函数ID可以找到其对应的函数地址,从而调用函数。如果在当前类对象的函数映射表中没有找到函数的话,就继续搜索其父类中(每个类对象的super_class 存储了父类的类对象地址),如果到达其根类还是没找到的话,会报运行时错误。 其过程如下图所示:

    
    
    消息的成功传递依赖于两个重要的要素,通过实例中的 isa指针找到实例所属的类对象,然后通过类对象中的消息映射表找到所要调用的函数。
    首先通过传递的selector参数找到消息映射表中的函数。然后调用函数,将实例的地址和参数传递给调用的这 个函数。最后返回返回值。 

    类类型的存在使objective-c拥有了运行时识别,动态创建,序列化等机制。


     3.消息接收者对象(指向消息接收者对象的指针)以及方法中指定的参数传递给方法实现 IMP。
     4.最后,将方法实现的返回值作为该函数的返回值返回。

    注:编译器会自动插入调用消息函数objc_msgSend,我们无须在代码中显示调用该消息函数。


五 消息传递小结

     到这里,我们已经大致明白了Objective-c 中消息的传递的整个过程。其实如果你熟悉MFC的话,你会发现Objective-c的运行时和MFC的RTTI挺像的。
    下图是MFC的运行时机制,CRuntimeClass相当于Objectiv-c的object_clas类对象,在CRuntimeClass中有指向基类函数的指针,与MFC不同的是object_class没有类似与m_pNext_ClassMFC成员。
     1.编译器会将消息转换为对消息函数 objc_msgSend的调用,该函数有两个主要的参数:消息接收者 receiver 和消息对应的方法ID,即SEL, 同时接收消息不定参数列表。

    2.objc_masSend 通过 receiver中的isa找到类对象,从而找到 SEL 对应的方法实现 IMP。注:因为不同的类对同一方法可能会有不同的实现,所以找到的方法实现依赖于消息接收者(receiver)。
下面再做一下详细消息传递过程:
                           
                           

       正因为有像CRuntimeClass和object_class这些类类型的存在才使得它们拥有了运行识别,动态创建,序列化等机制。


      下一节将对消息传递做进一步的深层次探究。




IOS中消息传递的8种方式Demo 一个Demo,几乎完整的介绍了全部IOS的传递方式,更多的参见我的博客 立即下载

相关推荐

手把手教你用ADS和CGH40010F模型搭建Doherty功放仿真原型(附工程文件)

本文详细介绍了如何使用ADS软件和CGH40010F GaN器件模型搭建Doherty功放仿真原型,涵盖工程准备、关键电路模块实现、效率优化技巧及常见问题排查。通过实战指南和效率优化技巧,帮助工程师快速掌握Doherty功放设计,提升5G基站和广播发射系统的功率放大器性能。

weixin_26897585的博客 345

[iOS]消息传递和消息转发

1.从本类的 method list (二分查找/遍历查找)查找imp2.从本类的父类的cache查找imp(汇编)3.从本类的父类的method list (二分查找/遍历查找)查找imp…继承链遍历…(父类->…->根父类)里找cache和method list的imp4.若上面环节有任何一个环节查找到了imp,跳出循环,缓存方法到本类的cache,并返回imp5.直到查找到nil,指定imp为消息转发,跳出循环,执行动态方法解析resolveMethod_locked。

weixin_61196797的博客 1937

Smart200 PLC实现Bool信号接通延时、关闭延时作用

解决Smart200 PLC时间继电器和脉冲扫描P或N不能重复使用的问题,用于Bool信号延时接通和延时关闭的作用,可调整时间基数

gk_121的博客 4319

Objective-C method及相关方法分析

## Objective-C method及相关方法分析 转载请注名出处 [http://blog.youkuaiyun.com/uxyheaven](http://blog.youkuaiyun.com/uxyheaven/article/details/38120335) 本篇文章将探究一下objc里的关于方法的函数是怎样实现的 首先看下方法的定义, Method 是一个objc_metho...

weixin_34198762的博客 166

kaggle——销量预测的baseline(M5 Forecasting - Accuracy)

前言 在刚刚结束的kaggle比赛M5 Forecasting - Accuracy中,因为是第一次参加,笔者也是花了大量的时间和精力在上面,最终拿到一块银牌(所以我拿到了大学第一个考试挂科。。。求求电磁场老师高抬贵手给点平时分放我一马吧。。。早上看到kaggle成绩异常兴奋,中午考完直接爆炸=。=),当然运气占了很大因素,这次比赛private leadboard的shake up非常大,排名波动几千名都存在的。笔者运气不错,是向上的shake:)。这里总结一下销量预测的基本流程。 从下图可以看到这次比

weixin_43901221的博客 5432

写给小白的“具身智能”入门科普

智能”,大家都懂,也就是AI。那么,什么是“具身”?“具身”是一个很小众的名词,通常都出现在哲学、认知科学领域。它的英文叫Embodied,是embody的过去式和过去分词。em-表示“进入,使……”,-body表示“身体”。组合起来,就是“使……进入身体”。Embodied Intelligence(具身智能),顾名思义,就是“使智能进入身体”、“给智能一个身体”的意思。那么,具身智能,是不是就是“AI+身体”呢?这样说并不准确。

欢迎来到我的博客 1821

【iOS】—— 消息传递和消息转发

检查接受者是否存在,为nil则不做任何处理;通过receiverdeisa指针找到对应的class类对象;找到类对象之后通过内存平移找到cache;从cache中获取buckets;从buckets中对比sel,查看是否有同名方法;如果有对应的sel,就会进入到cacheHit,调用imp;如果没有对应的sel,进入objc_msgSend_uncached,然后到lookUpImpOrForward(慢速查找)。

qq_72437394的博客 2073

【HALCON工业视觉应用探索】10. C#+Halcon 3D视觉实战:点云处理与三维测量工业指南(附完整代码与实操案例)

摘要:本文聚焦C#+Halcon在3D视觉领域的工业应用,从新手友好的“基础3D检测系统”切入,逐步深入“汽车铸件三维测量”等工业级场景。内容涵盖核心概念(点云数据结构、3D采集原理、坐标系统)、完整技术流程(数据采集→预处理→特征提取→三维测量→结果可视化)、工业级代码实现(多视角点云融合、微缺陷检测、高精度尺寸测量),以及现场落地关键技巧(硬件选型、标定流程、抗干扰优化)。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 2004

iOS——消息传递和消息转发

从本类的 method list (二分查找/遍历查找)查找imp从本类的父类的cache查找imp(汇编)从本类的父类的method list (二分查找/遍历查找)查找imp:…继承链遍历…(父类->…->根父类)里找cache和method list的imp若上面环节有任何一个环节查找到了imp,跳出循环,缓存方法到本类的cache,并返回imp直到查找到nil,指定imp为消息转发,跳出循环,执行动态方法解析resolveMethod_locked。

m0_73348697的博客 2566

MATLAB与ROS联合仿真——实例程序搭建思路

MATLAB与ROS联合仿真——实例程序搭建思路

慕羽★的博客 5229

uniapp [安卓苹果App端] - 实现微信支付功能+拉起微信付款支付后返回本app页面,详解uniApp如何唤起本机微信app并跳转到支付页面全流程及示例源码(uniapp实现微信支付,可打包)

uni-app项目在APP端使用微信支付功能,uniapp前端实现微信支付,uniapp开发安卓App对接微信支付,uniapp苹果ios唤起微信支付,uniapp调用微信支付uniapp开发app-调用微信支付,uniapp开发安卓苹果app如何接入微信支付,前后端应该怎么做,UniApp中实现微信支付功能,支付报错,调起失败没响应,uniapp苹果微信支付唤起实现,app唤起微信支付,拉起微信支付,uniapp中唤醒微信进行支付并返回app,uniApp调起微信支付失败报错,全网最详细的uniapp微信

🏆 前端领域优质创作者 1万+

【iOS】运行时消息传递与转发机制

前言 Objective-C是一门非常动态的语言,以至于确定调用哪个方法被推迟到了运行时,而非编译时。与之相反,C语言使用静态绑定,也就是说,在编译期就能决定程序运行时所应该调用的函数,所以在C语言中,如果某个函数没有实现,编译时是不能通过的。而Objective-C是相对动态的语言,运行时...

chuange6363的博客 171

硬核反坑!YOLOv5训练避坑指南:根治梯度消失、不收敛、检测漏框三大核心问题(附实战代码+调优清单)

数据是基础,超参数是关键,模型是工具,训练策略是保障。梯度消失、不收敛、检测漏框这三大问题,本质上都是“数据-模型-训练”不匹配的结果。梯度消失/爆炸:优先调整学习率策略+梯度裁剪,其次优化模型结构;训练不收敛:优先清洗数据集,其次调优超参数,最后检查配置文件;检测漏框:优先重新聚类锚框,其次增强浅层特征,最后调整推理参数。YOLOv5训练的最高境界,不是调参,而是让数据、模型、训练策略三者完美匹配。按本文的方法反坑,你的YOLOv5训练一定能一次成功!🚀。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 233

IOS运行时(消息传递)

0 Tag标签:消息   一 函数调用概述 view sourceprint? 1.Objective-C不支持多重继承(同Java和Smalltalk),而C++语言支持多重继承。 Objective-C是动态绑定,它的类库比C++要容易操作。Objective-C 在运行时可以允许根据字符串名字来访问方法和类,还可以动态连接和添加类。

yongyinmg的专栏 1069

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

IOS -运行时 (消息传递再探究)

IOS运行时消息传递过程再讲解。

zzbjut 3249

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

iOS-runtime详解(一)消息传递中的各种结构

文章目录理解消息传递。objc_msgSend的作用边界情况Self & SuperObject & Class & Meta ClasiSA详解小插曲,来看看什么是关联对象实例回到iSAISA()消息传递中如何找寻方法。Methodclass_data_bits_t bits;lldb打印验证class_ro_t *的结构realizeClassWithoutSwift小总结参考文章 理解消息传递。 objc_msgSend的作用 在OC中对象调用方法,叫做传递消息。消息有name

wtl1804的博客 556

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

iOS runtime再学习

iOS面试专题一 几乎是默写出来,加上自己理解的博客(iOS面试) 继承自NSObject的对象才可以用runtime runtime的作用:可以把闭源的iOS变为开源

baidu_40537062的博客 622

浅议运行时

iOS在执行功能时,会尽可能从编译和链接时推迟到运行时。运行时系统扮演的角色就行我们的电脑系统一样,而我们编写的程序就像在Windows系统里的QQ、QQ音乐,运行时提供给我们程序的运行环境和交互。程序和运行时系统的交互首先,代码的执行必须要和运行时系统进行交互,要不然运行是系统怎么能够知道你要干什么?1.通过Objective-C源代码交互 当编译器要编译Objective-C时,将自动创建一些

NeXTSTEP110的博客 445

运行时runbime

iOS_运行时runtime 最终效果图: 打开XCode帮助文档,搜索Objective-C Runtime 找到结果共6章,如下所示: This document has the following chapters: “Runtime Versions and Platforms” “Interacting wi

我是个程序猿 513

iOS RunTime理解笔记

iOS:RunTime(运行时) RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。 对于C语言,函数的调用在编译的时候会决定调用哪个函数。编译完成之后直接顺序执行,无任何异议。 OC的函数调用被称为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编译时,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言...

qq_39848087的博客 235

iOS应用程序安全(3)-理解Objective-C Runtime

作者:Prateek Gianchandani 译者:吴发伟 原文网址:http://resources.infosecinstitute.com/ios-application-security-part-3-understanding-the-objective-c-runtime/ 版权声明:自由转载-非商用-保持署名 引言 基本上所有的iOS应用都是用Objective-

疯狂原始人 1441

浅谈Runtime运行时

runtime runtime又叫运行时,是一套底层的c语言api,其为iOS内部核心之一。OC是动态运行时语言,它会将一些工作放在代码运行时去处理,而非编译时,比如动态的遍历属性和方法,动态的添加属性和方法,动态的修改属性和方法等。 了解runtime,首先要先了解它的核心--消息传递。 消息传递 消息直到运行时才会与方法实践绑定起来。 一个实例对象调用实例方法,像这样[obj doSometh...

架构师亮哥的博客 905

iOS 消息(即方法调用)的两个隐藏参数 :self 和 _cmd

iOS 消息(即方法调用)的两个隐藏参数 :self 和 _cmd

太阳火神的美丽人生 4388

iOS运行时Runtime浅析

运行时是iOS中一个很重要的概念,iOS运行过程中都会被转化为runtime的C代码执行。例如[target doSomething];会被转化成objc)msgSend(target,@selector(doSomething))来执行。这篇博客会较为全面的来讲解下Runtime。        OC是一门动态语言,它将很多静态语言在编译和链接时做的事放到了运行时来处理。这种动态语言的优势在于

LANGZI7758521的专栏 477
上一篇: IOS - 运行时 (多态)
下一篇: IOS -运行时 (消息传递再探究)
张哲BJUT
博客等级 码龄15年 151粉丝 111原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值