当前位置: 首页 > news >正文

【iOS】isKindOfClass和isMemberOfClass方法

前言

这个归根结底还是在考察我们对isa走向图和类的继承的理解,也就是苹果官方这幅图:
在这里插入图片描述

接下来的函数调用流程请参考这张图。

1 isKindOfClass方法

1.1 objc_opt_isKindOfClass C函数

查看源码可发现,无论是谁调用isKindOfClass方法都会进入这个C函数。(这个C函数位于NSObjective.mm

// Calls [obj isKindOfClass]
// 当obj调用isKindOfClass时,objc_opt_isKindOfClass会被触发
// obj是一个id类型,id是一个objc_object结构体指针,意味着,传进来的可以是时类,也可以是类的实例对象
// otherClass就是isKindOfClass的参数,我们当初传进去的cls
BOOL objc_opt_isKindOfClass(id obj, Class otherClass)
{
#if __OBJC2__if (slowpath(!obj)) return NO;Class cls = obj->getIsa();	 // 此处的cls仅是obj的第一个isaif (fastpath(!cls->hasCustomCore())) {// otherClass 从obj的ISA开始,依次和ISA的父类比较,直到找到或者父类为nil结束// 当父类为nil意味着最后一个和otherClass比较的是NSObject根类。for (Class tcls = cls; tcls; tcls = tcls->superclass) {if (tcls == otherClass) return YES;}return NO;}
#endifreturn ((BOOL(*)(id, SEL, Class))objc_msgSend)(obj, @selector(isKindOfClass:), otherClass);
}

可知:

  1. 一切皆从调用者objisa开始,然后顺着superclass走下去,直到找到clssuperclassnil结束。
  2. superclassnil,意味着最后的根类NSObject也不是cls,返回flase

1.2 类SubClass调用+ (BOOL)isKinsOfClass:(Class)cls

流程:

  1. 从类的isa——元类开始,判断它不是cls
  2. 如果是,返回true
  3. 如果不是,继续用元类的superclasscls比较,看是不是cls
  4. 直到根类NSObject也比较完。

判断顺序: SubClassMetaClass->MetaClass->...->RootMetaClass->NSObject

总结:

  • 判断cls是不是 元类->父类的元类->父父类的元类->…->根元类->NSObject (元类的superclass继承链)其中一个。
  • cls 传除NSObject.class外的任意类对象均为false

1.3 元类MetaClass 调用+ (BOOL)isKinsOfClass:(Class)cls

流程:

  1. MetaClassISA 指向 RootMetaClass ,所以从 RootMetaClass 开始比较判断是不是我们传入的cls;
  2. 如果不是,再看根类NSObject是不是,如果NSObject也不是,就彻底没有了,返回false

判断顺序:MetaClassRootMetaClass->NSObject

总结:

  • 判断cls是不是 根元类->NSObject 中的任意一个。

1.4 对象obj 调用- (BOOL)isKinsOfClass:(Class)cls

流程:

  1. isa指向的类对象开始,判断是不是cls
  2. 如果不是,看类对象的父类,逐级判断是不是cls
  3. 直到找到返回true,或者判断到NSObject依然不是,返回false结束。

判断顺序: objectSubClass -> SubClass ->...->NSObject

总结:

  • 判断cls是不是 类对象->父类->…->NSObject (superclass继承链)其中一个。

2 isMemberOfClass

2.1 类对象SubClass调用+ (BOOL)isMemberOfClass

源码:

+ (BOOL)isMemberOfClass:(Class)cls {return self->ISA() == cls;
}

不用像isKindOfClass循环直到找到或nil,他只要比较cls是不是我当前的isa指向,是返回true,不是返回false。

判断:SubClassMetaClass

2.2 元类MetaClass 调用+ (BOOL)isMemberOfClass

因为元类的isa只指向根元类NSObejct ,所以除了NSObject的类SubClass以外,传入任何类对象也都是false。

验证传入NSObject的类SubClass的结果:

void demo(void) {
//    BOOL re1 = [[NSObject class] isKindOfClass:[NSObject class]];Class rootMetaClass = object_getClass([NSObject class]);NSLog(@"%d", [[NSObject class] isMemberOfClass:rootMetaClass]);
}

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

2.3 对象obj调用 -(BOOL)isMemberofClass:(Class)clss

- (BOOL)isMemberOfClass:(Class)cls 底层源码:

- (BOOL)isMemberOfClass:(Class)cls {return [self class] == cls;
}
- (Class)class {return object_getClass(self); // 获取当前的isa指向的类
}

只要判断对象的isa,也就是图中的SubClass是不是我们传入的cls。

3. 测试

void demo(void) {BOOL f1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];BOOL f2 = [(id)[MyClass class] isKindOfClass:[MyClass class]];BOOL f3 = [(id)[MySuperClass class] isKindOfClass:[MySuperClass class]];BOOL f4 = [(id)[MyClass class] isKindOfClass:[MySuperClass class]];BOOL f5 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];BOOL f6 = [(id)[MyClass alloc] isKindOfClass:[NSObject class]];BOOL f7 = [(id)[MySuperClass alloc] isKindOfClass:[NSObject class]];NSLog(@"NSObjectClass ISKindOf NSObjectClass:%d", f1);NSLog(@"MyClassClass ISKindOf MyClassClass:%d", f2);NSLog(@"MySuperClassClass ISKindOf MySuperCassClass:%d", f3);NSLog(@"MyClassClass ISKindOf MySuperClassClass:%d", f4);NSLog(@"NSObjectObj ISKindOf NSObjectClass:%d", f5);NSLog(@"MyClassObj ISKindOf NSObjectClass:%d", f6);NSLog(@"MySuperClassObj ISKindOf NSObjectClass:%d", f7);}

测试结果:
在这里插入图片描述

相关文章:

【iOS】isKindOfClass和isMemberOfClass方法

前言 这个归根结底还是在考察我们对isa走向图和类的继承的理解,也就是苹果官方这幅图: 接下来的函数调用流程请参考这张图。 1 isKindOfClass方法 1.1 objc_opt_isKindOfClass C函数 查看源码可发现,无论是谁调用isKindOfClass方法都会…...

李飞飞「具身智能」VoxPoser:0预训练完成复杂指令

机器人接入大模型听懂人话 论文地址: https://voxposer.github.io/voxposer.pdf 项目主页: https://voxposer.github.io/ 参考链接: [1]https://twitter.com/wenlong_huang/status/1677375515811016704 [1]https://www.amacad.org/publicatio…...

前端八股文

info 毕业设计(课题、方向 本科毕业设计:家庭医生签约管理系统后台开发(微信小程序) 硕士课题:医学图像分割(婴儿脑分割) 51062319991129351X 邮编 重庆市南岸区 400000 13183849783 // 18728097929 // 13158442955 中国广电四川网络股份有限公司中江…...

前端年度工作述职报告优秀

前端年度工作述职报告优秀篇1 尊敬的各位领导、各位同仁: 大家好!按照20__年度我公司就职人员工作评估的安排和要求,我认真剖析、总结了自己的工作情况,现将本人工作开展情况向各位领导、同仁做以汇报,有不妥之处,希…...

【MyBatis 学习一】认识MyBatis 第一个MyBatis查询

目录 一、认识MyBatis 1、MyBatis是什么? 2、为什么要学习MyBatis? 二、配置MyBatis环境 1、建库与建表 2、创建新项目 3、xml文件配置 (1)配置数据库连接 (2)配置 MyBatis 中的 XML 路径 三、测试&#x…...

TCP 和 UDP

TCP(Transmission Control Protocol,传输控制协议) 是面向连接的协议,即在收发数据前,必须和对方建立可靠的连接,TCP的头部为20个字节。 UDP(User Datagram Protocol,用户数据报协…...

springboot配置自定义数据源(Druid德鲁伊)的步骤。

今天和大家分享下在Springboot中配置自定义数据源Druid的两种方法及步骤。 方法一: 1.在pom.xml配置依赖(注释里面的内容) 2.配置自己的数据源设置,我是在yaml文件中配置的,顺便提醒一下,在配置yaml文件的时候缩进问题一定要注意…...

K8S:容器日志收集与管理

Kubernetes 里面对容器日志的处理方式,都叫作 cluster-level-logging,即:这个日志处理系统,与容器、Pod 以及 Node 的生命周期都是完全无关的。这种设计当然是为了保证,无论是容器挂了、Pod 被删除,甚至节点…...

Flutter系列文章-Flutter进阶

在前两篇文章中,我们已经了解了Flutter的基础知识,包括Flutter的设计理念、框架结构、Widget系统、基础Widgets以及布局。在本文中,我们将进一步探讨Flutter的高级主题,包括处理用户交互、创建动画、访问网络数据等等。为了更好地…...

【C++】C++11右值引用|新增默认成员函数|可变参数模版|lambda表达式

文章目录 1. 右值引用和移动语义1.1 左值引用和右值引用1.2 左值引用和右值引用的比较1.3右值引用的使用场景和意义1.4 左值引用和右值引用的深入使用场景分析1.5 完美转发1.5.1 万能引用1.5.2 完美转发 2. 新的类功能2.1 默认成员函数2.2 类成员变量初始化2.3 强制生成默认函数…...

rust学习-线程

Rust 标准库只提供了 1:1 线程模型 Rust 是较为底层的语言,如果愿意牺牲性能来换取抽象,以获得对线程运行更精细的控制及更低的上下文切换成本,使用实现了 M:N 线程模型的 crate 示例 use std::thread; use std::time::Duration;fn main() …...

题目:2180.统计各位数字之和为偶数的整数个数

​​题目来源: leetcode题目,网址:2180. 统计各位数字之和为偶数的整数个数 - 力扣(LeetCode) 解题思路: 暴力遍历即可。 解题代码: class Solution {public int countEven(int num) {int re…...

3dsmax制作一个机器人

文章目录 建模身子:眼睛:头饰:肩膀手臂腿调整细节 渲染导出objMarmoset Toolbag 3.08渲染给眼睛添加材质,设置为自发光添加背景灯光 建模 身子: 眼睛: 头饰: 肩膀 手臂 腿 调整细节 渲染 导出…...

C++的类型转换运算符:reinterpret_cast

C的类型转换运算符:reinterpret_cast reinterpret_cast 是 C 中与 C 风格类型转换最接近的类型转换运算符。它让程序员能够将一种对象类型转换为另一种,不管它们是否相关;也就是说,它使用如下所示的语法强制重新解释类型&#xf…...

flask中的cookies介绍

flask中的cookies介绍 “Cookie” 在 web 开发中是一种非常重要的技术,用于在客户端(即用户的浏览器)存储信息,以便在多个页面和多个访问会话之间保持状态。Cookies 通常用于记住用户的登录信息,跟踪用户在站点上的浏…...

adnroid 11. 0 Activity启动流程图解

从Launcher到ActivityTaskManager 从ActivityTaskManagerService 到 ApplicationThread 从ApplicationThread到onCreate...

了解Unity编辑器之组件篇Physics(四)

Physics:用于处理物理仿真和碰撞检测。它提供了一组功能强大的工具和算法,用于模拟真实世界中的物理行为,使游戏或应用程序更加真实和可信。 主要用途包括: 碰撞检测:Unity Physics 提供了高效的碰撞检测算法&#x…...

“数字中华 点亮未来”中华线上客户节 盛大开幕

2023年是中华保险数字化转型落地之年,峥嵘37载,中华保险在数字化转型上已经涌现了一批彰显辨识度、具有影响力的应用成果。7月15日,中华保险围绕数字化转型之路开展以“数字中华 点亮未来”为主题的37周年线上客户节活动,倾力打造…...

中文分词入门:使用IK分词器进行文本分词(附Java代码示例)

1. 介绍 中文分词是将连续的中文文本切分成一个个独立的词语的过程,是中文文本处理的基础。IK分词器是一个高效准确的中文分词工具,采用了"正向最大匹配"算法,并提供了丰富的功能和可定制选项。 2. IK分词器的特点 细粒度和颗粒…...

CTFSHOW web 信息收集

web入门的刷题 web1 教我们多看看源代码 web2 抓包 web3 抓包 web4 robots.txt robots.txt web5 phps源代码泄露 phps 就是php的源代码 用户无法访问 php 只可以通过phps来访问 web6 源代码备份 web7 git web8 svn web9 swp /index.php.swp web10 cookie web11 查域名…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...

Spring Boot面试题精选汇总

🤟致敬读者 🟩感谢阅读🟦笑口常开🟪生日快乐⬛早点睡觉 📘博主相关 🟧博主信息🟨博客首页🟫专栏推荐🟥活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线, n r n_r nr​ 根接收天线的 MIMO 系…...