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

iOS——消息传递和消息转发机制 首先我们了解了什么是消息发送,明白了OC语言中所有对象的方法调用都是消息发送。其次我们知道了消息发送是SEL-IMP的查找过程调用resolveInstanceMethod或者resolveClassMethod作为动态解析方法给本类一个补救的方法去动态添加没有实现的方法的实现调用forwardingTargetForSelector让别的对象去执行这个函数(消息转发)forwardInvocation灵活的将目标函数以其他形式执行(我们的这个完整的消息转发的实现可以很简单https。... 阅读详情
一 消息查找优化
	至此,我们已经明白了Objective-c中大致的消息传递过程,我们发现如果每次函数调用都经历上面的过程(,那函数调用的效率就会很低,尤其是当类的继承层次很多的时候,它需要一层层的查找其效率将会更低,为了加快查找调用的速度,Objective-c对消息查找做了优化。
	从前一节的类对象我们知道它含有一个 struct objc_cache *cache成员,这个缓存就是为了提高查找的效率的。每个类都有自己的缓存,同时包括继承的方法和在该类中定义的方法。当我们在查找IMP 时:

     1.首先去该类的方法 cache 中查找,如果找到了就返回它
     2.如果没有找到,就去该类的方法列表中查找。如果在该类的方法列表中找到了,则将 IMP 返回,并将它加入cache中缓存起来。根据最近使用原则,这个方法再次调用的可能性很大,缓存起来可以节省下次调用再次查找的开销。
     3.如果在该类的方法列表中没找到对应的 IMP,在通过该类结构中的 super_class指针在其父类结构的方法列表中去查找,直到在某个父类的方法列表中找到对应的IMP,返回它,并加入cache中。

     4.如果在自身以及所有父类的方法列表中都没有找到对应的 IMP,则进入下文中要讲的消息转发流程。


二 消息转发
      给一个对象发送它不能处理的消息会得到出错提示,然而,Objective-C运行时系统在抛出错误之前,会给消息接收对象发送一条特别的消息forwardInvocation 来通知该对象,该消息的唯一参数是个NSInvocation类型的对象——该对象封装了原始的消息和消息的参数。

我们可以实现forwardInvocation:方法来对不能处理的消息做一些默认的处理,也可以将消息转发给其他对象来处理,而不抛出错误。
       关于消息转发的作用,可以考虑如下情景:假设,我们需要设计一个能够响应negotiate消息的对象,并且能够包括其它类型的对象对消息的响应。 通过在negotiate方法的实现中将negotiate消息转发给其它的对象来很容易的达到这一目的。
      更进一步,假设我们希望我们的对象和另外一个类的对象对negotiate的消息的响应完全一致。一种可能的方式就是让我们的类继承其它类的方法实现。 然而,有时候这种方式不可行,因为我们的类和其它类可能需要在不同的继承体系中响应negotiate消息。
       虽然我们的类无法继承其它类的negotiate方法,但我们仍然可以提供一个方法实现,这个方法实现只是简单的将negotiate消息转发给其他类的对象,就好像从其它类那儿“借”来的现一样。如下所示:
- negotiate  {
    if ([someOtherObject respondsToSelector:@selector(negotiate)])
        return  [someOtherObject negotiate];
    return self;
}
      这种方式显得有欠灵活,特别是有很多消息都希望传递给其它对象时,我们就必须为每一种消息提供方法实现。此外,这种方式不能处理未知的消息。当我们写下代码时,所有我们需要转发的消息的集合都必须确定。然而,实际上,这个集合会随着运行时事件的发生,新方法或者新类的定义而变化。
     forwardInvocation:消息给这个问题提供了一个更特别的,动态的解决方案:当一个对象由于没有相应的方法实现而无法响应某消息时,运行时系统将通过forwardInvocation:消息通知该对象。每个对象都从NSObject类中继承了forwardInvocation:方法。然而,NSObject中的方法实现只是简单地调用了doesNotRecognizeSelector:。通过实现我们自己的forwardInvocation:方法,我们可以在该方法实现中将消息转发给其它对象。
 要转发消息给其它对象,forwardInvocation:方法所必须做的有:
     1.决定将消息转发给谁,并且
     2.将消息和原来的参数一块转发出去
消息可以通过invokeWithTarget:方法来转发:

- (void) forwardInvocation:(NSInvocation *)anInvocation
{
    if ([someOtherObject respondsToSelector:[anInvocation selector]])
        [anInvocation invokeWithTarget:someOtherObject];
    else
        [super forwardInvocation:anInvocation];
} 
     转发消息后的返回值将返回给原来的消息发送者。您可以将返回任何类型的返回值,包括: id,结构体,浮点数等。
       forwardInvocation:方法就像一个不能识别的消息的分发中心,将这些消息转发给不同接收对象。或者它也可以象一个运输站将所有的消息都发送给同一个接收对象。它可以将一个消息翻译成另外一个消息,或者简单的"吃掉“某些消息,因此没有响应也没有错误。forwardInvocation:方法也可以对不同的消息提供同样的响应,这一切都取决于方法的具体实现。该方法所提供是将不同的对象链接到消息链的能力。
注意: forwardInvocation:方法只有在消息接收对象中无法正常响应消息时才会被调用。 所以,如果我们希望一个对象将negotiate消息转发给其它对象,则这个对象不能有negotiate方法。否则,forwardInvocation:将不可能会被调用。

三 小结
        现在当我们回过头来在看http://blog.youkuaiyun.com/zhangzhebjut/article/details/24134863中的实例应该明白了IOS中整个函数的调用流程。IOS的运行时还是挺强大的,通过对运行时的学习,对Objective-c类型系统有一个更加深刻的了解。
         其实如果熟悉Python的人应该也知道,Python是一个全动态的语言,它的类型系统和Objective-c有些相像,有时间给我会将其与Objective-c做一个详细的对照。

深入探究iOS系统服务与SVC调用机制 在iOS操作系统中,系统服务组件(System Service Components, SVC)扮演着至关重要的角色,它作为iOS系统内核的核心组成部分之一,负责协调和管理各种系统级服务,如时间管理、进程控制、权限验证等。SVC通过提供一系列标准化的接口,使得应用程序能够在不直接与内核交互的情况下,间接地利用系统资源和功能。Mach内核是构建在微内核概念之上的,是苹果iOS系统的核心之一。它的主要功能是提供基础的抽象服务,比如进程间通信(IPC)。 阅读详情

相关推荐

用 dism 合并与删除 wim 映像

一、合并 假设 installA.wim 有 3 个映像,installB.wim 有 1 个映像。 1、全部合并 将 installA.wim 中的 3 个卷映像合并到 installB.wim 中,这样 installB.wim 中的卷映像增加到 4 个。 dism/export-image/sourceimagefile:d:\installA.wim/sourceindex:1/destinationimagefile:d:\installB.wim dism/export-image/source

KefanWon的博客 5199

ios应用程序加载分析(一)

`_dyld_start`(dyld)->`doModInitFunctions`(dyld)->`libSystem_initializer`(libSystem)->`libdispatch_init`(libdispatch)->`_objc_init`(libobjc)->`registerObjCNotifiers`(dyld): sNotifyObjCMapped=mapped;&&sNotifyObjCInit=init;&&sNotifyObjCUnmapped = unmapped;

coding不死,也未曾凋零 3530

STM32异常与中断过程详解

1. 异常与中断概念引入 异常主要是指来自CPU内部的意外事件,比如执行了未定义指令、算术溢出、除零运算等发生在CPU内部的意外事件,这些异常的发生,会引起CPU运行相应的异常处理程序;中断一般来自硬件(如片上外设、外部I/O输入等)发生的事件,当这些硬件产生中断信号时,CPU会暂停当前运行的程序,转而去处理相关硬件的中断服务程序。但无论是异常还是中断,都会引起程序执行偏离正常的流程,转而去执行异常/中断的处理函数。 下面对异常和中断的介绍,如果中断信号的产生原因来自CPU内部,则称之为异常;如果中断信号来

luobeihai的博客 1万+

invoke原理_小试 Xcode 逆向:App 内存监控原理初探(逆向技术必看)

小试 Xcode 逆向:App 内存监控原理初探(逆向技术必看)前言最近看到公司同事的《iOS内存那些事》系列文章,其中的一篇文章讲了他在研究WebKit中内存管理的时候,发现可以用phys_footprint来衡量内存,其结果和xcode debug显示的值基本一致。文章通读下来,收获颇丰~回味之余,突然脑洞了一下,为啥不直接逆向一下Xcode,学习一下xcode debug app时它是怎么实...

weixin_42524864的博客 246

从零部署奥比中光Gemini335L:Python SDK编译与手眼标定环境实战

本文提供了一份从零部署奥比中光Gemini 335L深度相机的完整实战指南。详细介绍了驱动安装、Python SDK编译、CMake配置及虚拟环境搭建等关键步骤,并重点解析了如何通过编译生成Python模块,最终实现深度图与点云数据获取,为后续的机械臂手眼标定工作奠定坚实基础。

weixin_29031161的博客 398

零代码搭建专业知识库:Wiki.js+cpolar让团队协作像写笔记一样简单

"项目文档又找不到了!“团队负责人小张第N次在群里看到这样的抱怨——技术文档分散在邮件、网盘和个人电脑里,新人入职要花一周熟悉文档位置,远程协作时版本混乱更是家常便饭。Wiki.js与cpolar内网穿透服务的出现,就像给团队协作装上了"中央大脑”,用写Markdown笔记的简单方式,搭建一个专业的知识库系统。普通人对知识管理的需求其实很简单:方便记录、容易查找、大家能用。但传统方案把这个过程搞得异常复杂:建服务器、配环境、学语法、搞权限……大部分团队还没开始就放弃了。

Yawesh的博客 2040

OC-消息转发

当对象接收到消息后发现没有实现该消息的方法 则他会调用//这个方法是属于NSObject类然后这个方法会调用/用于生产错误信息 表示异常NSInvalidArgumentException发生 无法处理参数选择器对应的消息所以我们只需要重定义这个方法就行了forwardInvocation需要传入NSInvocation的对象 这个对象存储了目标,选择器,参数等消息转发所需要的全部元素。..................

qq_43535469的博客 860

FANUC机器人_CRX协作机器人的开机和示教器的初始化设置基本步骤(二)

FANUC机器人_CRX协作机器人的开机和示教器的初始化设置基本步骤

Robot_PLC_HMI_Automation 2732

iOS 性能优化

1、弱应用 __weak typeof(self) weakSelf = self; __strong typeof(self) strongSelf = weakSelf; 2、NSTimer 方法一: #import <objc/runtime.h> @property (nonatomic, strong) NSTimer *timer; @property (no...

RangingWon的博客 380

【信息系统项目管理师】高分论文:论信息系统项目的整合管理(绩效考核系统)

我们将项目管理计划中的子计划包括项目范围、进度、成本、质量管理计划,过程改进计划,人力资源管理计划,风险、采购管理计划,干系人管理计划,项目范围、成本、进度基准作为依据,查看项目的各个方面,通过组织全体团体成员会议来解读由各监控过程提供的信息,之后我与项目管理团队一起制订所需措施,确保项目绩效达到预期要求。在一个项目中,变更是必然的,也是不可避免的,进度拖延,成本失控,客户有新的需求等都会引起项目的变更。在本项目中,我要求有处于工作状态的产品,开发人员才可以对其任意修改,修改完成后,重新入库即可。

数据知道的博客 6887

深入Scrapy ItemLoader:打造优雅高效的Python爬虫数据清洗流水线

ItemLoader是 Scrapy 提供的声明式数据加载工具。它的核心理念是:将数据提取(从response中取原始值)和数据清洗/验证(处理空值、格式转换、默认值等)分离开。你可以把它想象成一个工厂流水线:原始零件(selector提取的文本)进入,经过一道道工序(输入处理器),组装成最终产品(Item字段)。首先在items.py中定义清晰的数据结构。使用搭配类型注释(虽然Scrapy自身不强制,但对人和IDE友好)。

2201_76125261的博客 68

iOS中可以直接调用 某个对象的消息

在 iOS中可以直接调用 某个对象的消息 方式有3种 1.performSelector:withObject: 2.NSInvocation 3.objc_msgSend performSelector:withObject: 方式比较简单,能完成简单的调用。但是对于>2个的参数或者有返回值的处理,那就需要做些额外工作才能搞定. @interface MyCl

ZBrightz的专栏 1273

十九、帧间预测编码_2、解码、显示顺序与图像管理、参考帧管理

一、基本概念 1.1H.264的解码顺序和显示顺序: 解码过程中,每一帧的数据按照相应的NAL Unit在码流中的顺序传入解码器进行解码 由于B帧的存在,视频帧在输出时会进行顺序重排 1.2frame_num与POC frame_num:表示解码顺序 POC:表示显示顺序(picture_order_count) 在H.264的码流中,表示解码顺序和显示顺序分别有相应的语法元素表示。这两个值都会在码流中保存,并在读取slice信息时解析(SliceHeader中) 1.3参考帧列表 某一帧图像在解

叮咚的博客 1330

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

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

m0_73348697的博客 2566

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

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

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

qq_72437394的博客 2073

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【iOS】——消息传递底层实现

OC在编译时会根据方法的名字(包括参数序列),生成一个用来区分这个方法的唯一的一个ID,这个ID就是SEL类型的。如果在当前类对象的缓存中找到了转发的条目(imp == forward_imp),表示在父类的缓存中找到了转发的方法实现。第一 个参数代表接收者也就是方法调用者,第二个参数代表方法选择器(SEL 是选择子的类型)也就是方法的名字,后续参数就是消息中的 那些参数,其顺序不变。最后,在循环结束后,会根据需要将找到的方法实现缓存到类对象的缓存中,然后解锁运行时锁,并根据需要返回找到的方法实现或空值。

m0_73974920的博客 1521

老版QQ原生表情gif动态

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

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

摘要: Objective-C的消息传递机制基于objc_msgSend函数,通过三步查找方法实现。若未找到,触发消息转发的三级补救。

2301_80467753的博客 1409

[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

IOS中消息传递的8种方式

一 MVC简介 MVC是将应用中的类组织起来的一种策略。是IOS开发最常用的设计模式,当然,还有诸如MVVM,VIPER等模式,不过不在本文的讨论范畴。 MVC代表什么:Model-View-Controller。 Model:应用是什么(what the app is ) Controller:如何呈现Mo

Leo的专栏 5046

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

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

chuange6363的博客 171

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

本篇文章简单的介绍了消息传递和消息转发。

2301_80253909的博客 1249

IOS -运行时 (消息传递 )

IOS运行时 消息传递详述。

zzbjut 4603

iOS底层原理系列03-Objective-C运行时机制

存在形式:分类由category_t结构体表示,而扩展没有单独的结构体。加载时机:分类在运行时动态加载,扩展在编译期就与原类合并。实例变量:分类不能添加实例变量,扩展可以添加实例变量。方法覆盖:分类可以覆盖原类方法,多个分类之间按编译顺序覆盖;扩展的方法和原类方法等价,不存在覆盖关系。源码要求:分类可以为任何类添加功能,扩展只能为有源码的类添加功能。

但行好事,莫问前程;不忘初心,方得始终! 1585

iOS开发——使用delegate进行消息传递

iOS开发中,界面之间传递消息或者数据是最基本的一种需求,我们可以使用很多方法来实现这种需求,比如在头文件中暴露一个属性、比如使用notification等等。今天我们要来介绍另一种方式:使用delegate传递消息。        delegate称为委托,同时也是一种代理设计模式。使用委托避免了类与类的耦合度过高。利用委托赋值更加安全可控,委托赋值在不暴露自己类的属性的前提下就可以对自己进行

乞力马扎罗的雪CYF的博客 4464

iOS Runtime运行机制详解(消息传递、消息转发)

一直想发关于Runtime的文章,但是由于读的资料一多,对Runtime的理解又加深了一些,所以总是改来改去,导致一篇都没发出来(其实是因为懒)。 最近又有小伙伴问我,我也只好再次补老账了。。。 ---------啥是OC Runtime---------- OC Runtime呢,其实就是一个Runtime库。 (那啥是Runtime库呢?给你个小链接:https://www.cnblo...

ws1836300的博客 1720

iOS 运行时详解

注:本篇文章转自:http://www.jianshu.com/p/adf0d566c887 一、运行时简介 Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。对于Objective-C来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行。Runtime基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。在R...

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值