【iOS】—— isMemberOfClass isKindOfClass以及源码

news2024/11/14 13:55:09

【iOS】—— isMemberOfClass & isKindOfClass以及源码

    • isa指针
    • 示例
    • 源码解析:
      • isKindOfClass:源码解析(实例方法和类方法)
      • isMemberOfClass:源码解析(实例方法和类方法)
      • 源码分析总结:

isa指针

isa指针的指向: 对象的 isa 指向 类; 类的 isa 指向 元类;元类的 isa 指向 根元类;根元类的 isa 指向 自己。
类的superclass的指向: 类的 superclass 指向 父类, 父类的 superclass 指向 根类 ,根类的superclass 指向 nil。
元类的superclass的指向: 元类的 superclass 指向 父类的元类,父元类的 superclass 指向 根类的元类 根元类的 superclass 指向 根类 根类的 superclass 指向 nil。

示例

 int main(int argc, const char * argv[]) {
    @autoreleasepool {
       //iskindOfClass & isMemberOfClass 类方法调用
       BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];
       BOOL re2 = [(id)[Person class] isKindOfClass:[Person class]];
       BOOL re3 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];
       BOOL re4 = [(id)[Person class] isMemberOfClass:[Person class]];
       NSLog(@" re1 :%hhd\n re2 :%hhd\n re3 :%hhd\n re4 :%hhd\n",re1,re2,re3,re4);
       
       //iskindOfClass & isMemberOfClass 实例方法调用
       BOOL re5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];
       BOOL re6 = [(id)[Person alloc] isKindOfClass:[Person class]];
       BOOL re7 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];
       BOOL re8 = [(id)[Person alloc] isMemberOfClass:[Person class]];
       NSLog(@" re5 :%hhd\n re6 :%hhd\n re7 :%hhd\n re8 :%hhd\n",re5,re6,re7,re8);
 
    }
    return 0;
}

运行的结果:
在这里插入图片描述

源码解析:

isKindOfClass:源码解析(实例方法和类方法)

//--isKindOfClass---类方法、对象方法
//+ isKindOfClass:第一次比较是 获取类的元类 与 传入类对比,再次之后的对比是获取上次结果的父类 与 传入 类进行对比
+ (BOOL)isKindOfClass:(Class)cls {
    // 获取类的元类 vs 传入类
    // 根元类 vs 传入类
    // 根类 vs 传入类
    // 举例:LGPerson vs 元类 (根元类) (NSObject)
    for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}
 
//- isKindOfClass:第一次是获取对象类 与 传入类对比,如果不相等,后续对比是继续获取上次 类的父类 与传入类进行对比
- (BOOL)isKindOfClass:(Class)cls {
/*
获取对象的类 vs 传入的类 
父类 vs 传入的类
根类 vs 传入的类
nil vs 传入的类
*/
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

isMemberOfClass:源码解析(实例方法和类方法)

//类方法
//+ isMemberOfClass : 获取类的元类,与 传入类对比
+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}
//实例方法
//- isMemberOfClass : 获取对象的类,与 传入类对比
- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
} 

源码分析总结:

isKindOfClass:

类方法:元类 --> 根元类 --> 根类 --> nil 与 传入类的对比。
实例方法:对象的类 --> 父类 --> 根类 --> nil 与 传入类的对比。

isMemberOfClass:

类方法: 类的元类 与 传入类对比。
实例方法:对象的父类 与 传入类对比。

通过上面的源码解析分析代码:

ret1 = 1,传入的cls为NSObject,self指的是NSObject,进入循环。 第一次循环:是NSObject meta与NSobject进行比较,不相等,tcls = tcls->superclass ,此时 tcls 指向 NSobject meta 的父类 ,即 NSObject。进入第二次循环。 第二次循环:此时 tcls 为 NSobject,cls 依然是 NSobject,执行判断条件 if (tcls == cls) 相等,return YES。
所以 re1 的结果为 1。

ret2 = 0,传入的cls为Person,self指的是Person,进入循环 第一次循环:tcls为Person meta,cls为Person类;不相等,执行tcls = tcls->superclass, 此时 tcls 指向 NSobject metal。进入第二次循环。 第二次循环:tcls 为 NSobject meta ,cls 为 Person类;不相等,执行 tcls = tcls->superclass ,此时 tcls 指向 NSObject。进入第三循环。 第三次循环: tcls 为 NSobject ,cls 为 Person类;不相等,执行 tcls = tcls->superclass ,此时 tcls 指向 nil。不满足for循环执行条件 tcls。结束循环。
所以 re2 的结果为 0。

ret3 = 0 : 传入的cls 为 NSObject, self 指向 NSObject
self->ISA( ) ,self的 isa 指向 NSObject meta ;NSObject meta 与 NSObject 不相等。
所以 re3 的结果为 0。

ret4 = 0 : 传入的cls 为 Person, self 指向 Person
self->ISA( ) ,self的 isa 指向 Person meta ;Person meta 与 Person 不相等。
所以 re4 的结果为 0。

ret5 = 1 : 传入的cls 为 NSObject 类,self 指向 NSObject 的 实例对象
第一次循环:tcls 指向 NSObject 类,cls 为 NSObject 类,执行判断 if (tcls == cls) ,相等,return YES,结束循环。
所以 re5 返回 1。

ret6 = 1 : 传入的cls 为 Person 类,self 指向 Person 的 实例对象
第一次循环:tcls 指向 Person 类,cls 为 Person 类,执行判断 if (tcls == cls) ,相等,return YES,结束循环。
所以 re6 返回 1。

ret7 = 1 : 传入的cls 为 NSObject, self 指向 NSObject 对象
[self class] 为 NSObject 类 ;与 cls 相等。
所以 re7 的结果为 1。

ret8 = 1 : 传入的cls 为 Person, self 指向 Person 对象
[self class] 为 Person 类 ;与 cls 相等。
所以 re8 的结果为 1。

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

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

相关文章

MF173:将多个工作表转换成PDF文件

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…

【C++】16. set 和 map

在之前的博客中,我们已经接触过STL中的部分容器,比如:vector、list、deque等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面存储的是元素本身。 我们这篇博客的内容是关联式容器&#xff…

负重3Kg垂起固定翼无人机技术详解

一、基本参数 负重3Kg垂起固定翼无人机是一款具备强大负载能力和长航时特性的无人机。其基本参数如下: - 最大负载:3Kg - 最大续航时间:203分钟(示例数据,实际续航时间可能根据任务负载、环境条件等因素有所不同&…

敲详细的springframework-amqp-rabbit源码解析

看源码时将RabbitMQ的springframework-amqp-rabbit和spring-rabbit的一套区分开,springboot是基于RabbitMQ的Java客户端建立了简便易用的框架。 springboot的框架下相对更多地使用消费者Consumer和监听器Listener的概念,这两个概念不注意区分容易混淆。…

【electron6】浏览器实时播放PCM数据

pcm介绍:PCM(Puls Code Modulation)全称脉码调制录音,PCM录音就是将声音的模拟信号表示成0,1标识的数字信号,未经任何编码和压缩处理,所以可以认为PCM是未经压缩的音频原始格式。PCM格式文件中不包含头部信…

FPGA文档阅读

FPGA的文档没有相应的基础还真不容易看懂,下面是B站上对FPGA文档的解读(本文非对文档解读,只是为个人记录第三期:CycloneIV E最小系统板设计(一)从Datasheet上获取FPGA的基本参数_哔哩哔哩_bilibili 电源部份 核心电…

elasticsearch, kibana, 6.8.18 版本下的创建索引,指定timestamp,java CRUD,maven版本等

ELK 这一套的版本更迭很快, 而且es常有不兼容的东西出现, 经常是搜一篇文章,看似能用,拿到我这边就不能用了。 很是烦恼。 我这边的ELK版本目前是 6.8.18,这次的操作记录一下。 (涉密内容略有删改&#xf…

SQL语句——DDL数据定义语言

1.sql语言不区分大小写 2._(下划线)进行名字的分割,不适用驼峰命名 3.; 语句sql结尾处加一个;来表示结束 4.一般关键词建议用大写 5.所有名称不能用中文 1.创建数据库 CREATE DATABASE [IF NOT EXISTS] 库名 -- 库 #创建库 #create databa…

计算机网络序章

计算机网络学习什么? 下列举例由用户使用计算机角度去理解 首先,计算机网络是通过路由等方式去获取我们希望的数据用户可以在APP中去进行方便的操作去获取数据。每个应用都有自己的端口去确定每次来的数据是否是自己需要的数据应该应该传到哪里&#x…

COD论文笔记 Deep Gradient Learning for Efficient Camouflaged 2022

动机 这篇论文的动机在于解决伪装目标检测(COD)中的一个关键问题:在复杂背景下,伪装目标与背景的边界模糊,使得检测变得极其困难。现有的方法,如基于边界或不确定性的模型,通常仅响应于伪装目标的稀疏边缘&#xff0c…

oceanbase架构、功能模块、数据存储、特性、sql流转层等概念详解

一、架构图 OceanBase 数据库采用无共享(Shared-Nothing)分布式集群架构,各个节点之间完全对等,每个节点都有自己的 SQL 引擎、存储引擎、事务引擎,运行在普通 PC 服务器组成的集群之上,具备高可扩展性、高…

澎湃算力 玩转AI 华为昇腾AI开发板——香橙派OriengePi AiPro边缘计算案例评测

澎湃算力 玩转AI 华为昇腾AI开发板 香橙派OriengePi AiPro 边缘计算案例评测 人工智能(AI)技术正以前所未有的速度改变着我们的生活、工作乃至整个社会的面貌。作为推动这一变革的关键力量,边缘计算与AI技术的深度融合正成为行业发展的新趋势…

秒懂C++之类与对象(下)

目录 一.static成员 测试: 二.explicit关键字 三.友元(少用) 友元函数: 友元类: 四.内部类(少用) 五.(扩展)编译器的优化 一.static成员 测试: 实现一…

【分布式事务】怎么解决分布式场景下数据一致性问题

分布式事务的由来 拿充值订单举个栗子吧,假设:原本订单模块和账户模块是放在一起的,现在需要做服务拆分,拆分成订单服务,账户余额服务。原本收到充值回调后,可以将修改订单状态和扣减余额放在一个mysql事务…

邮件安全篇:邮件传输加密(SSL/TLS or STATRTTLS)

1. 前言 使用过邮件客户端的同学一定见过下面这张图。这是客户端账号配置界面,里面有SSL、STARTTLS选项。刚接触邮件客户端的同学肯定会有这些疑问:什么是SSL?什么是STARTTLS?两者有什么区别?具体该如何选择呢&#x…

首批通过 | 百度通过中国信通院H5端人脸识别安全能力评估工作

2024年5月,中国信息通信研究院人工智能研究所依托中国人工智能产业发展联盟安全治理委员会(AIIA)、“可信人脸应用守护计划”及多家企业代表共同开展《H5端人脸识别线上身份认证安全能力要求及评估方法》的编制工作,并基于该方法开…

创新驱动的力量:探索Web3在技术发展中的作用

随着科技的不断进步和创新,Web3作为新一代互联网技术范式,正在以其去中心化、安全、透明和可编程的特性,深刻影响着全球技术发展的方向和速度。本文将深入探讨Web3技术的核心概念、关键特征以及其在技术创新中的重要作用,展示其在…

【Android】Fragment的静态动态创建以及两种创建方式的生命周期

参考: 33.3-Fragment的创建-静态创建2_哔哩哔哩_bilibili Fragment的创建_从现有代码创建foutran-CSDN博客 【Android】Fragment的基本用法、Fragment和活动间的通信、Fragment的生命周期、动态加载布局的技巧_android fragment-CSDN博客 文章目录 Fragment的静态创…

贝锐蒲公英远程运维方案:即装即用、无需专线,断网也可远程维护

目前,公路、隧道、桥梁、航道,甚至是施工现场和工业生产环境等,都采用了实时监测方案。 通过部署各类传感器和摄像头等设备,现场视频画面和控制单元(如PLC、工控机等)数据可以实时回传,用于集中…

0711springNews新闻系统管理 实现多级评论

0611springmvc新闻系统管理-CSDN博客 0711springNews新闻系统管理项目包 实现多级评论-CSDN博客 数据库字段 需要添加父节点id,通过该字段实现父评论和子评论的关联关系。 对象属性 实现链表,通过一个父评论可以找到它对应的所有子孙评论。 业务层 实现…