【iOS】isMemberOfClassisKindOfClass

目录

    • 前言
    • class方法
    • isMemberOfClass和isKindOfClass
      • 实例方法分析
      • 类方法分析
    • 实例验证
    • 总结


前言

认识这两个方法之前,首先要了解isa指向流程和继承链(【iOS】类对象的结构分析)关系,以便理解得更透彻

上经典图:

请添加图片描述

要注意的是:根类(NSObject)的元类isa是根元类,根元类的父类superclassNSObject

class方法

实例调用class方法就是获取isa所指:

- (Class)class {return object_getClass(self);
}Class object_getClass(id obj)
{if (obj) return obj->getIsa();else return Nil;
}

类调用class方法就是返回本身Class

typedef struct objc_class *Class;+ (Class)class {return self;
}

isMemberOfClass和isKindOfClass

objc4源码

+ (BOOL)isMemberOfClass:(Class)cls {return self->ISA() == cls;
}- (BOOL)isMemberOfClass:(Class)cls {return [self class] == cls;
}+ (BOOL)isKindOfClass:(Class)cls {for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {if (tcls == cls) return YES;}return NO;
}- (BOOL)isKindOfClass:(Class)cls {for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {if (tcls == cls) return YES;}return NO;
}

实例方法分析

- (BOOL)isMemberOfClass:(Class)cls

此方法用于判断self(调用者)类型cls指定类)是否是同一个类,是就返回YES,否则返回NO。因为每个类对象在内存中只存在一份,所以可以用==判断

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

- (BOOL)isKindOfClass:(Class)cls

此方法用于判断self(调用者)类型cls指定类或者其父类)是否是同一个类,是就返回YES,否则就沿着继承链向上查找,只要有一个类与cls使用一个类,就返回YES,如果直到NSObject还没有找到,再向上就为nil,返回NO

- (BOOL)isKindOfClass:(Class)cls {for (Class tcls = [self class]; tcls; tcls = tcls->getSuperclass()) {if (tcls == cls) return YES;}return NO;
}

类方法分析

类方法的调用者是Class类对象,按照isa指向,对比的应该是meta-class元类对象

+ (BOOL)isMemberOfClass:(Class)cls

此方法判断self(调用者)的isa元类)是否是指定元类(元类也是Class类型)

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

+ (BOOL)isKindOfClass:(Class)cls

此方法实现与其对象方法的实现类似,只是对比的是元类及元类的继承链
判断self(调用者)的isa元类)是否是指定类的元类或者其父类的元类,是就返回YES,否则就沿着继承链向上找到根元类,最后如果沿着superclass直到NSObject还没找到,再向上就为nil,返回NO

+ (BOOL)isKindOfClass:(Class)cls {for (Class tcls = self->ISA(); tcls; tcls = tcls->getSuperclass()) {if (tcls == cls) return YES;}return NO;
}

实例验证

下面通过调用上面的方法,来验证以上的分析:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>@interface Person : NSObject@end@implementation Person@endint main(int argc, const char * argv[]) {@autoreleasepool {BOOL res1 = [[NSObject class] isKindOfClass: [NSObject class]];BOOL res2 = [[Person class] isKindOfClass: [Person class]];BOOL res3 = [[NSString class] isKindOfClass: [NSObject class]];NSLog(@"%d %d %d", res1, res2, res3);  // 1 0 1Person* person = [[Person alloc] init];BOOL res4 = [[Person class] isKindOfClass: [NSObject class]];BOOL res5 = [person isKindOfClass: [NSObject class]];NSLog(@"%d %d", res4, res5);  // 1 1//  获取一个类的元类的两种方式
//        Class objectMeta = objc_getMetaClass("NSObject");Class objectMeta = object_getClass([NSObject class]);
//        Class personMeta = objc_getClass("Person");Class personMeta = object_getClass([Person class]);//        BOOL res6 = [[NSObject class] isMemberOfClass: objectMeta];  res6 == 1BOOL res6 = [[NSObject class] isMemberOfClass: [NSObject class]];BOOL res7 = [person isMemberOfClass: [NSObject class]];
//        BOOL res8 = [[Person class] isMemberOfClass: personMeta]; res8 == 1BOOL res8 = [[Person class] isMemberOfClass: [NSObject class]];BOOL res9 = [person isMemberOfClass: [Person class]];NSLog(@"%d %d %d %d" , res6, res7, res8, res9); // 0 0 0 1}return 0;
}
  • isMemberOfClass
    • res1中调用的是类方法,沿着元类继承链找到NSObject类对象
    • res2中调用的是类方法,沿着元类继承链不会找到Person类对象
    • res3中调用的是类方法,沿着元类继承链找到NSObject类对象
    • res4中调用的是类方法,沿着元类继承链找到NSObject类对象
    • res5中调用的是对象方法,沿着继承链找到NSObject类对象
  • isKindOfClass
    • res6中调用的是类方法,对比的是元类对象,传入的是类对象
    • res7中调用的是对象方法,Person显然跟NSObject不是同一类
    • res8中调用的是类方法,对比的是元类对象,传入的是类对象
    • res9中调用的是对象方法,personPerson

上面的代码中,注释掉的res6res8中传入的是相应的元类对象,则结果为1

总结

那张isa指向和继承链流程图很经典!很重要!
结合源码会对这两个方法理解得更透彻
再分得清这两个方法的调用者是class(类对象)还是instance(实例对象)

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

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

相关文章

AM62x和rk3568的异同点

AM62x 和 RK3568 是两款不同的处理器&#xff0c;分别来自 Texas Instruments&#xff08;TI&#xff09;和 Rockchip。它们在设计目标、架构、性能和应用领域等方面存在一些异同。以下是这两款处理器的对比&#xff1a; 1. 基本架构 AM62x&#xff1a; 架构&#xff1a;基于…

与大数据相关的 Python 第三方库和工具

Python 在大数据领域有着广泛的应用&#xff0c;以下是一些与大数据相关的 Python 第三方库和工具&#xff1a; 1. **Pandas**&#xff1a;Pandas 是 Python 中最常用的数据处理和分析库之一&#xff0c;提供了高效的数据结构和数据分析工具&#xff0c;可以进行数据清洗、转换…

机器学习数学基础(1)--线性回归与逻辑回归

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 1 线性回归和逻辑回归与机器学习的关系 线性回归属于机器学习 – 监督学习 – 回归 – 线性回归&#xff0c; 逻辑…

Maven概述

目录 1.Maven简介 2.Maven开发环境搭建 2.1下载Maven服务器 2.2安装&#xff0c;配置Maven 1.配置本地仓库地址 2.配置阿里云镜像地址 2.3在idea中配置maven 2.4在idea中创建maven项目 3.pom.xml配置 1.项目基本信息 2.依赖信息 3.构建信息 4.Maven命令 5.打包Jav…

企业微信报错,api forbidden 错误码 48002

业务场景是这边后端页面点同步就去企微接口拉取客户数据&#xff0c;然后报错如下。 后端抓包返回的json如下 {“errcode”:48002,“follow_user”:[],“errmsg”:“api forbidden, hint: [1721869790252850672734303], from ip: 203.88.203.216, more info at https://open.w…

数据结构(链表)

&#x1f30f;个人博客主页&#xff1a;心.c 前言&#xff1a; 最近练习算法回去学了链表&#xff0c;收获挺大的&#xff0c;大概内容整理了一下&#xff0c;语言是用c写的&#xff0c;所以在这里分享给大家&#xff0c;希望大家可以有所收获 &#x1f525;&#x1f525;&…

2024年技校大数据实验室建设及大数据实训平台整体解决方案

随着信息技术的迅猛发展&#xff0c;大数据已成为推动产业升级和社会进步的重要力量。为适应市场需求&#xff0c;培养高素质的大数据技术人才&#xff0c;技校作为职业教育的重要阵地&#xff0c;亟需加强大数据实验室的建设与实训平台的打造。本方案旨在提出一套全面、可行的…

Synchronized关键字和乐观锁(CAS)

一、Sychronized关键字 在Java中&#xff0c;synchronized 是一个关键字&#xff0c;用于实现线程同步。当一个方法或一个代码块被synchronized修饰时&#xff0c;它被称为同步方法或同步代码块。这意味着每次只有一个线程可以进入该方法或代码块&#xff0c;其他线程必…

二维码的生成与识别(python)

二维码生成 from PIL import Image import qrcode from qrcode.image.styledpil import StyledPilImage from qrcode.image.styles.colormasks import SolidFillColorMask from qrcode.image.styles.moduledrawers import SquareModuleDrawer# 创建二维码对象 qr qrcode.QRCo…

Windows系统笔记本无法连接Wi-Fi常见原因及解决办法

在现代生活中&#xff0c;Wi-Fi已成为我们连接互联网不可或缺的方式之一。 然而&#xff0c;有时我们的Windows系统笔记本可能会遇到无法连接Wi-Fi的问题。 这种情况可能由多种原因引起&#xff0c;包括硬件故障、驱动问题、系统设置等。 以下是针对Windows 10和Windows 11系…

【STM32】stm32中GPIO_ReadInputDataBit()是什么意思

GPIO_ReadInputDataBit()函数用于读取指定GPIO端口的某一引脚上的电平状态&#xff0c;并返回该引脚的电平是高电平&#xff08;1&#xff09;还是低电平&#xff08;0&#xff09;。 在STM32单片机中&#xff0c;GPIO&#xff08;General-Purpose Input/Output&#xff09;端…

vue3在元素上绑定自定义事件弹出虚拟键盘

最近开发中遇到一个需求: 焊接机器人的屏幕上集成web前端网页, 但是没有接入键盘。这就需要web端开发一个虚拟键盘,在网上找个很多虚拟键盘没有特别适合,索性自己写个简单的 图片: 代码: (代码可能比较垃圾冗余,也没时间优化,凑合看吧) 第一步:创建键盘组件 为了方便使用…

【Django】 读取excel文件并在前端以网页形式显示-安装使用Pandas

文章目录 安装pandas写views写urls安装openpyxl重新调试 安装pandas Pandas是一个基于NumPy的Python数据分析库&#xff0c;可以从各种文件格式如CSV、JSON、SQL、Excel等导入数据&#xff0c;并支持多种数据运算操作&#xff0c;如归并、再成形、选择等。 更换pip源 pip co…

Flink SQL 实时读取 kafka 数据写入 Clickhouse —— 日志处理(三)

文章目录 前言Clickhouse 表设计adlp_log_local 本地表adlp_log 分布式表 Flink SQL 说明创建 Source Table (Kafka) 连接器表创建 Sink Table (Clickhouse) 连接器解析 Message 写入 Sink 日志查询演示总结 前言 在之前的文章中&#xff0c;我们总结了如何在 Django 项目中进…

构建智慧水利系统,优化水资源管理:结合物联网、云计算等先进技术,打造全方位、高效的水利管理系统,实现水资源的最大化利用

本文关键词&#xff1a;智慧水利、智慧水利工程、智慧水利发展前景、智慧水利技术、智慧水利信息化系统、智慧水利解决方案、数字水利和智慧水利、数字水利工程、数字水利建设、数字水利概念、人水和协、智慧水库、智慧水库管理平台、智慧水库建设方案、智慧水库解决方案、智慧…

spring-boot3.x整合Swagger 3 (OpenAPI 3) +knife4j

1.简介 OpenAPI阶段的Swagger也被称为Swagger 3.0。在Swagger 2.0后&#xff0c;Swagger规范正式更名为OpenAPI规范&#xff0c;并且根据OpenAPI规范的版本号进行了更新。因此&#xff0c;Swagger 3.0对应的就是OpenAPI 3.0版本&#xff0c;它是Swagger在OpenAPI阶段推出的一个…

Unity判断鼠标是否在UI上

Unity判断鼠标是否在UI上 下值等于true表示在UI上 EventSystem.current.IsPointerOverGameObject()可用来判断滚轮滑动缩放视角功能&#xff0c;在UI上滑动滚轮视角不缩放&#xff0c;反之缩放。

Python开发日常总结

1、命令总结 1.1 conda创建、激活、退出虚拟环境 conda create --name myenv python3.8 # 创建 conda create --name myenv python3.9 # 激活 conda activate myenv # 退出 conda deactivate

产品系统的UI暗色系和浅色系模式切换是符合人体视觉工程学的设计

视觉革命&#xff1a;UI设计中的暗夜与黎明 UI设计如同夜空中最亮的星辰&#xff0c;引领着用户穿梭于信息的海洋。而今&#xff0c;一场视觉革命正在悄然上演&#xff0c;它关乎于我们的眼睛&#xff0c;关乎于我们的体验——那就是产品系统的UI暗色系和浅色系模式的切换。如…

手写一个JVM自定义类加载器

1. 自定义类加载器的意义 隔离加载类&#xff1a;在某些框架内进行中间件与应用的模块隔离&#xff0c;把类加载到不同的环境。比如&#xff1a;阿里内某容器框架通过自定义类加载器确保应用中依赖的jar包不会影响到中间件运行时使用的jar包。再比如&#xff1a;Tomcat这类Web…