【Effective_Objective-C_2对象,消息,运行期2】

news2024/11/13 23:24:23

文章目录

  • 前言
  • 12.理解消息转发机制
            • 消息转发
            • 动态方法解析
            • 动态方法解析的前提
            • 备援接受者
            • 完整的消息转发
        • 消息转发全部流程
      • 要点总结
  • 13.用“方法调配技术”调试“黑盒方法”
        • 方法调配
        • 动态消息派发系统和IMP
        • 如何交换方法实现
      • 要点总结
  • 14.理解“类对象”的用意
        • 在类的继承体系中查询类型信息
      • 要点总结
  • 总结

前言

  • 继续学习本书第二章内容

12.理解消息转发机制

  • 之前强调了消息是如何传递下去的,这一条深入理解一下在某些出现问题的时刻系统是如何解决问题的。
消息转发
  • 某个对象收到了无法解读的消息之后会发生什么情况?这就是OC的消息转发机制。
  • 对于在编译期向类发出的无法解读的消息之后不会报错,因为可以在运行期继续向类里面添加方法,所以在编译时期出现了对象无法解读的消息就会启动消息转转发机制。
  • 消息转发分为两大阶段,第一阶段先征询接收者,所属的类,看其是否能动态添加方法,处理当前这个“未知的选择子”,这叫做“动态方法解析”。第二阶段涉及“完整的消息转发机制”。
动态方法解析
  • 对象在收到了无法解读的消息,首先调用其所属类的下列类方法
    请添加图片描述
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    
}

该方法的参数就是那个未知的选择子,其返回值为Boolean类型,表示这个类是否能新增一个实例方法用以处理此选择子。在继续往下执行转发机制之前,本类有机会新增一个处理此选择子的方法,假如尚未实现的方法不是实例方法而是类方法,那么运行期系统就会调用另一个方法,该方法与“resolveInstanceMethod:”类似,叫做“resolveClassMethod”。
请添加图片描述

动态方法解析的前提
  • 对于上述的消息转发第一步,前提是我们相关的实现代码已经写好了,只需要等着运行时的时候插入类里面即可在属性那一条的@dynamic属性就是利用该方案实现的
备援接受者
  • 在第一步还是没有找到写好的方法之后,当前接受者还有第二次机会处理未知的选择子,在这一步里运行期的系统会询问接受者能不能找到其他接受者处理该消息,这里也有一个方法
    请添加图片描述
- (id)forwardingTargetForSelector:(SEL)aSelector {
    ;
}
  • 这个方法的参数代表未知的选择子,若当前接受者能找到备援对象,则将其返回,否则返回nil。这个方法其实也实现在了某个对象内部,可能存在其他一些列对象,该对象可以经过此方法处理了某些选择子的相关对象返回。
  • 需要注意的是这一步转发的消息我们是无法进行操作的,如需要操作,需要进行下一步,完整的消息转发机制
完整的消息转发
  • 对于消息转发机制,如果到了这一步就必须启动完整的消息转发机制。
  • 首先创建NSInvocation对象,把与尚未处理的那条消息有关的全部细节都封于其中。此对象包含选择子、目标及参数。在触发NSInvocation对象时,“消息派发系统”将亲自出马,把消息指派给目标对象。此步骤会调用下列方法来转发消息:
- (void)forwardInvocation:(NSInvocation *)anInvocation 
  • 这个方法的实现方式🈶️2种,一种是只需要改变调用目标,和备援接受者方法实现的等效,第二种则是在触发消息前,先以某种方式改变消息内容,比如追加另一个参数,或者改变选择子等
  • 实现此方法时,若发现某调用操作不应由本类来处理,则需调用超类的同名方法。这样的话,继承体系中的每个类都有机会处理此调用请求,直至NSObject。如果最后调用NSObject类的方法,那么该方法还会继而调用“doesNotRecognizeSelector:”以抛出异常,此异常表明选择子最终未能得到处理。
- (void)doesNotRecognizeSelector:(SEL)aSelector

请添加图片描述

  • 这些方法都在最大的NSObject里面实现

消息转发全部流程

  • 一张图总结
    请添加图片描述
  • ⚠️注意:往往越简单越好,能在第一步解决就不要去第二步,能改动目标实现就不要去执行第三步。

要点总结

  • 若对象无法响应某个选择子,则进入消息转发流程。
  • 通过运行期的动态方法解析功能,我们可以在需要用到某个方法时再将其加入类中。
  • 对象可以吧其无法解读的某些选择子转交给其他对象来处理。
  • 经过上述两步之后,如果还是没办法处理选择子,那就启动完整的消息转发机制。

13.用“方法调配技术”调试“黑盒方法”

  • 黑盒机制,不少人都有理解,就是一个方法你知道怎么用,如何用,并且常常都能使用它但是对于该方法的内部机制却不知道是什么样子,这一条就介绍了如何利用现有的方法去调试黑盒方法变成我们所能用的。

方法调配

  • 对于OC对象收到消息之后使用何种方法在运行期进行解析,与给定的选择子名称相对应的方法是可以在运行期改变的!这是OC语言强大的特性,我们就可以不知道源代码并且不需要通过继承子类复写方法来改变某个类本身的功能,这样一来新功能能够在本类实例化的所有实例里面生效,而不是仅限于覆写了相关方法的那些子类的实例。叫做方法调配

动态消息派发系统和IMP

  • 类的方法列表会把选择子的名称映射到相关的方法实现上面,使得动态消息派发系统能够根据此找到应该调用的方法,这些方法均以函数指针的形式表示,这种指针叫做IMP,原型如下
id (*IMP) (id, SEL, ...)

  • 例如NSString类可以响应自己所带的选择子,它们的关系类似于key 和 Value .
    请添加图片描述
  • OC运行期提供的几个方法都能操作这张表,开发者可以向其中新增选择子,也可以改变某选择子所对应的方法实现,还可以交选择子所映射到的指针,我们可以经过操作改变类的方法表
    请添加图片描述
  • 也就是说我们无需修改子类覆写方法,只需要修改方法表的布局,就会反映到程序所有NSString实例上

如何交换方法实现

  • 我们添加新功能的本质就是修改之前的方法实现,也就是重写写一个方法实现然后实现交换。
  • 方法交换函数
    请添加图片描述
  • 也就是说实现方法重写需要实现方法交换,实现方法交换就需要获取方法实现。这并不拗口
  • 方法交换实例
    请添加图片描述

要点总结

  • 在运行期,可以向类中新增或替换选择子所对应的方法实现。
  • 使用另一份实现来替换原有的方法实现,这道工序叫做“方法调配”,开发者常用此技术向原有实现中添加新功能。
  • 一般来说,只有调试程序的时候才需要在运行期修改方法实现,这种做法不宜滥用。

14.理解“类对象”的用意

在类的继承体系中查询类型信息

  • 这一条是我看的比较迷茫的一条,我总结出了我自己认为比较重要的。
  • 在OC里,之前说过存在类族模式,所以这里衍生出了两种方法。
  • isMemberOfClassisKindOfClass
    • “isMemberOfClass:”能够判断出对象是否为某个特定类的实例(只有与其出创建的类型相同时才返回YES),而“isKindOfClass:”则能够判断出对象是否为某类或其派生类的实例。
NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc] init];
    BOOL bool1 = [mutableDict isMemberOfClass:[NSDictionary class]];
    BOOL bool2 = [mutableDict isMemberOfClass:[NSMutableDictionary class]];
    BOOL bool3 = [mutableDict isKindOfClass:[NSDictionary class]];
    BOOL bool4 = [mutableDict isKindOfClass:[NSArray class]];

请添加图片描述

  • 这里和书上有些区别在bool2
    在这里插入图片描述
  • 书上的bool2 是yes,我的理解是NO,在前面我们学过类族,里面分了很多实际类,打印一下请添加图片描述
  • 确实不是一个类,但是bool3时yes 因为mutableDIct隶属于NSMutableDIctionary的子类

要点总结

  • 每个实例都有一个指向Class对象的指针,用以表明其类型,而这些Class对象则构成了类的继承体系。
  • 如果对象类型无法在编译期确定,那么就应该使用类型信息查询方法来探知。
  • 尽量使用类型信息查询方法来确定对象类型,而不要直接比较类对象,因为某些对象可能实现了消息转发功能。

总结

  • 第二章学的比较慢,每天学二,三条,有的东西还是需要手打到代码上鉴别一下,组长说书的内容有些老化,但这些知识还是很重要的,iOS路任重而道远。⛽️

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

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

相关文章

【经济学】【综合篇】经济机器是怎样运行的

原视频:经济机器是怎样运行的 (时长30分钟) Ray Dalio 前言:经济与我们每一个人息息相关,经济社会的一些变革或举措也会直接或间接的反映到我们每个个体身上。了解经济,提高自己的认知,可以帮助我们更好的参与经济活动…

excel数据统计技巧:如何对表格区域内所含字母进行计数

小王是一家快餐店的财务人员。受疫情影响公司开展了店外销售业务,所有销售采取手工记账的方式。为了简化销售人员的工作量,为每种商品指定了一个字母代码,营业员只需要记录每一单销售的商品代码即可。下面是根据手工记账登记的销售记录表&…

论文投稿指南——中国(中文EI)期刊推荐(第8期)

🎄🎄 EI是国际知名三大检索系统之一,在学术界的知名度和认可度仅次于SCI! 【前言】 想发论文怎么办?手把手教你论文如何投稿!那么,首先要搞懂投稿目标——论文期刊。其中,中文期刊的…

【运筹优化】子集和问题(Subset Sum Problems , SSP)介绍 + 动态规划求解 + Java代码实现

文章目录一、问题介绍二、动态规划求解思路三、Java代码实现一、问题介绍 子集和问题(Subset Sum Problems , SSP),它是复杂性理论中最重要的问题之一。 SSP会给定一组整数 a1,a2,....,ana_1,a_2,....,a_na1​,a2​,....,an​ ,…

手写Spring7(实现bean的初始化、销毁)

文章目录目标设计流程项目结构一、实现1、 定义初始化和销毁方法的接口2、Bean属性定义新增初始化和销毁3、执行 Bean 对象的初始化方法4、定义销毁方法适配器(接口和配置)5、定义注册销毁对象、销毁实现6、创建Bean时注册销毁方法对象7、虚拟机关闭钩子注册调用销毁方法二、测…

UNIAPP实战项目笔记55 自定义Tabbar并使用Tabbar事件拦截未登录跳转到登录页面

UNIAPP实战项目笔记55 自定义Tabbar并使用Tabbar拦截未登录跳转到登录页面 点击购物车和我的的时候需要拦截并验证登录 通过验证的直接跳转,为通过验证的跳转到登录页面 通过自定义tabbar来实现 实际案例图片 正常跳转 拦截跳转 代码 pages.json 页面配置 {"pages&qu…

JDBC编程相关知识(实现图书管理系统进阶版)

目录 一、配置MySQL数据库驱动包 二、JDBC常规操作 1、创建数据源 2、建立连接 3、操作数据库,执行sql语句 4、关闭资源 三、JDBC实现图书管理系统 1、建表 2、连接数据库 3、创建实体类 a、Book类 b、BookShelf类 c、User类 d、Administrator类 e、…

jsp+ssm计算机毕业设计大学生足球预约信息【附源码】

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: JSPSSM mybatis Maven等等组成,B/S模式 Mave…

java计算机毕业设计springboot+vue青少年编程在线考试系统

项目介绍 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存储达到准确、快速、完善,并能提高工作管理效率,促进其发展。 论文主要是对青少…

AIGC stable diffusion完整部署手册 for linux

准备工作 ( GPU服务器4G显卡 ): 1. 建议 Python3.10.7 以上的版本,最低不能低于3.10.5 2. pip pip3的版本升级到最新 pip 22.3.1 3. 安装python3.10.7之前先安装和升级 openssl-1.1.1q 4. yum安装源改成 阿里云 或者 清华 …

English Learning - L1-4 从此没有不会的表达(下) 2022.12.15 周四

English Learning - L1-4 从此没有不会的表达(下) 2022.12.15 周四5 动名词5.1 动名词都有什么作用作主语做表语做定语动名词做定语有啥讲究?做宾语5.2 动名词的复合结构---成功加入动名词自己的主语逻辑主语动名词复合结构作宾语时用普通格和…

2021年度汇总丨20大热门TWS耳机功能配置汇总解析

疫情下的时间匆匆而过,2021已成为过去,2022年正式开启。在过去的一年中,以TWS耳机为代表的音频市场依旧保持着健康稳定的发展,彰显这一市场超强的活力和朝好的未来发展。 回顾2021,这一年中,我爱音频网365天…

直线检测霍夫变换VS深度学习

1. 引言 直线检测有很多应用:例如,创建矢量化图、端点检测等。在这篇文章中,我们不讨论其具体的应用程序,而是重点关于于如何使用传统算法和深度学习的方法来进行直线检测,这里我们将对二者进行相关比较。 闲话少说&a…

经典算法之异或运算(无进位相加)

目录异或运算的定义异或运算的性质异或运算的应用交换两数翻转指定位寻找单身狗异或运算的定义 众所周知,计算机中的所有数据都是以二进制(0或者1)的形式存储。而异或运算符(^)就是将参加运算的两个数据,按…

C语言—数据类型

通过sizeof运算符获取数据类型的大小&#xff0c;int占4个字节&#xff0c;表示一个int变量可以存储32位的数据&#xff1b; vs2022中&#xff0c;sizeof运算符返回的结果是一个64位 (8bytes)的无符号整型的值&#xff0c;所以占位符要使用%lld&#xff1b; #include <std…

【空气起动系统控制】使用PID调节起动机入口压力值

前段时间师傅让做一个空起系统的建模&#xff0c;结果给忘了&#xff0c;现在趁着这几天疫情封控期间在家搞一搞&#xff0c;断断续续搞了五天&#xff0c;空起系统控制的相关资料太少了&#xff0c;还好最后弄出来了&#xff0c;虽然最后还存在点小问题&#xff0c;不过大体上…

【Java编程】SSH:Struts、Spring、Hibernate

SSH&#xff1a;Struts、Spring、HibernateSSH 框架指的是 Struts、Spring 和 Hibernate 三者的集成。集成 SSH 框架的系统从职责上分为表示层、业务逻辑层、数据持久层和域模块层。Struts 属于 MVC 框架的一种&#xff0c;提供了对 MVC 系统底层的支持&#xff0c;负责 MVC 的…

汽车ECU通信相关验证项有哪些?

已剪辑自: https://mp.weixin.qq.com/s/-fIAXkS37r6jvnuA7yIQDA 汽车电子的高速发展决定了基础软件所面临的要求将会更加严格&#xff0c;其要求会覆盖软件的安全性、稳定性、可扩展性等方方面面。为了提高软件质量&#xff0c;降低软件应用风险&#xff0c;构建高安全、高可靠…

什么是网站安全?如何查询网站在百度是否安全?

什么是网站安全&#xff1f; 百度词条的定义为网站安全是指出于防止网站受到黑客入侵者对其网站进行挂马&#xff0c;篡改网站源代码&#xff0c;被窃取数据等行为而做出一系列的安全防御工作&#xff0c;在我的理解中&#xff0c;网站安全就是当有人攻击你的网站时&#x…

Java+SSM社团管理系统(含源码+论文+答辩PPT等)

项目功能简介: 该项目采用的技术实现如下 后台框架&#xff1a;Spring、SpringMVC、MyBatis UI界面&#xff1a;JSP、jQuery 、H-ui 数据库&#xff1a;MySQL 系统功能 本社团管理系统是根据大学社团管理的实际应用而开发的&#xff0c;采用JSP技术&#xff0c;Java编程语言&am…