iOS - Runtime-API

news/2024/5/10 21:18:11

文章目录

  • iOS - Runtime-API
    • 1. Runtime应用
      • 1.1 字典转模型
      • 1.2 替换方法实现
      • 1.3 利用关联对象给分类添加属性
      • 1.4 利用消息转发机制,解决方法找不到的异常问题
    • 2. Runtime-API
      • 2.1 Runtime API01 – 类
        • 2.1.1 动态创建一个类(参数:父类,类名,额外的内存空间)
          • 2.2.1.1 示例
        • 2.2.1 注册一个类(要在类注册之前添加成员变量)
          • 2.2.2.1 示例
        • 2.2.3 销毁一个类
        • 2.2.4 获取isa指向的Class
        • 2.2.5 设置isa指向的Class
          • 2.2.5.1 示例
          • 2.2.5.2 调试信息
        • 2.2.6 判断一个OC对象是否为Class
          • 2.2.6.1 示例
        • 2.2.7 判断一个Class是否为元类
          • 2.2.7.1 示例
        • 2.2.8 获取父类
      • 2.2 Runtime API02 – 成员变量
        • 2.2.1 获取一个实例变量信息
        • 2.2.2 拷贝实例变量列表(最后需要调用free释放)
        • 2.2.3 设置和获取成员变量的值
        • 2.2.4 动态添加成员变量(已经注册的类是不能动态添加成员变量的)
        • 2.2.5 获取成员变量的相关信息
      • 2.3 Runtime API03 – 属性
        • 2.3.1 获取一个属性
        • 2.3.2 拷贝属性列表(最后需要调用free释放)
        • 2.3.3 动态添加属性
        • 2.3.4 动态替换属性
        • 2.3.5 获取属性的一些信息
      • 2.4 Runtime API04 – 方法
        • 2.4.1 获得一个实例方法、类方法
        • 2.4.2 方法实现相关操作
        • 2.4.3 拷贝方法列表(最后需要调用free释放)
        • 2.4.4 动态添加方法
        • 2.4.5 动态替换方法
        • 2.4.6 获取方法的相关信息(带有copy的需要调用free去释放)
    • 3. 示例
      • 3.1 示例1
      • 3.2 示例2
      • 3.3 示例3

iOS - Runtime-API

1. Runtime应用

开发过程中经常会用到Runtime,比如:

1.1 字典转模型

  • 利用Runtime遍历所有的属性或者成员变量
  • 利用KVC设值

1.2 替换方法实现

  • class_replaceMethod
  • method_exchangeImplementations

1.3 利用关联对象给分类添加属性

1.4 利用消息转发机制,解决方法找不到的异常问题

2. Runtime-API

2.1 Runtime API01 – 类

2.1.1 动态创建一个类(参数:父类,类名,额外的内存空间)
  • Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)
2.2.1.1 示例
// 动态创建一个类
Class newClass = objc_allocateClassPair([NSObject class], "ZSXDog", 0);
id dog = [[newClass alloc] init];
NSLog(@"");

执行结果:

2.2.1 注册一个类(要在类注册之前添加成员变量)
  • void objc_registerClassPair(Class cls)
2.2.2.1 示例
// 注册类
objc_registerClassPair(newClass);
2.2.3 销毁一个类
  • void objc_disposeClassPair(Class cls)
2.2.4 获取isa指向的Class
  • Class object_getClass(id obj)
2.2.5 设置isa指向的Class
  • Class object_setClass(id obj, Class cls)
2.2.5.1 示例
ZSXPerson *person = [[ZSXPerson alloc] init];
[person run];// 设置isa指向的Class
object_setClass(person, [ZSXCat class]);
[person run];

执行结果:

2.2.5.2 调试信息


2.2.6 判断一个OC对象是否为Class
  • BOOL object_isClass(id obj)
2.2.6.1 示例
ZSXPerson *person = [[ZSXPerson alloc] init];
NSLog(@"%d %d %d", object_isClass(person), object_isClass([ZSXPerson class]), object_isClass(object_getClass([ZSXPerson class])));

执行结果:

2.2.7 判断一个Class是否为元类
  • BOOL class_isMetaClass(Class cls)
2.2.7.1 示例
NSLog(@"%d %d", class_isMetaClass([ZSXPerson class]), class_isMetaClass(object_getClass([ZSXPerson class])));

执行结果:

2.2.8 获取父类
  • Class class_getSuperclass(Class cls)

2.2 Runtime API02 – 成员变量

2.2.1 获取一个实例变量信息
  • Ivar class_getInstanceVariable(Class cls, const char *name)
2.2.2 拷贝实例变量列表(最后需要调用free释放)
  • Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
2.2.3 设置和获取成员变量的值
  • void object_setIvar(id obj, Ivar ivar, id value)
  • id object_getIvar(id obj, Ivar ivar)
2.2.4 动态添加成员变量(已经注册的类是不能动态添加成员变量的)
  • BOOL class_addIvar(Class cls, const char * name, size_t size, uint8_t alignment, const char * types)
2.2.5 获取成员变量的相关信息
  • const char *ivar_getName(Ivar v)
  • const char *ivar_getTypeEncoding(Ivar v)

2.3 Runtime API03 – 属性

2.3.1 获取一个属性
  • objc_property_t class_getProperty(Class cls, const char *name)
2.3.2 拷贝属性列表(最后需要调用free释放)
  • objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
2.3.3 动态添加属性

BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes,
unsigned int attributeCount)

2.3.4 动态替换属性
  • void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes,
    unsigned int attributeCount)
2.3.5 获取属性的一些信息
  • const char *property_getName(objc_property_t property)
  • const char *property_getAttributes(objc_property_t property)

2.4 Runtime API04 – 方法

2.4.1 获得一个实例方法、类方法
  • Method class_getInstanceMethod(Class cls, SEL name)
  • Method class_getClassMethod(Class cls, SEL name)
2.4.2 方法实现相关操作
  • IMP class_getMethodImplementation(Class cls, SEL name)
  • IMP method_setImplementation(Method m, IMP imp)
  • void method_exchangeImplementations(Method m1, Method m2)
2.4.3 拷贝方法列表(最后需要调用free释放)
  • Method *class_copyMethodList(Class cls, unsigned int *outCount)
2.4.4 动态添加方法
  • BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
2.4.5 动态替换方法
  • IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
2.4.6 获取方法的相关信息(带有copy的需要调用free去释放)
  • SEL method_getName(Method m)
  • IMP method_getImplementation(Method m)
  • const char *method_getTypeEncoding(Method m)
  • unsigned int method_getNumberOfArguments(Method m)
  • char *method_copyReturnType(Method m)
  • char *method_copyArgumentType(Method m, unsigned int index)

3. 示例

3.1 示例1

// 动态创建一个类
Class newClass = objc_allocateClassPair([NSObject class], "ZSXDog", 0);
// 添加成员变量
class_addIvar(newClass, "_age", 4, 1, @encode(int));
class_addIvar(newClass, "_weight", 4, 1, @encode(int));
// 动态添加方法
class_addMethod(newClass, @selector(run), (IMP)run, "v@:");// 注册类
objc_registerClassPair(newClass);id dog = [[newClass alloc] init];
[dog setValue:@10 forKey:@"_age"];
[dog setValue:@20 forKey:@"_weight"];
[dog run];NSLog(@"%@ %@", [dog valueForKey:@"_age"], [dog valueForKey:@"_weight"]);// 在不需要的时候释放
dog = nil; //需要先释放示例对象
objc_disposeClassPair(newClass); //注销类

执行结果:

3.2 示例2

@interface ZSXPerson : NSObject@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *name;@end
// 获取成员变量信息
Ivar ageIvar = class_getInstanceVariable([ZSXPerson class], "_age");
NSLog(@"%s %s", ivar_getName(ageIvar), ivar_getTypeEncoding(ageIvar));// 设置和获取成员变量的值
Ivar nameIvar = class_getInstanceVariable([ZSXPerson class], "_name");ZSXPerson *person = [[ZSXPerson alloc] init];
object_setIvar(person, nameIvar, @"123");
//        object_setIvar(person, ageIvar, @10); //不能直接这样设置
object_setIvar(person, ageIvar, (__bridge id)(void *)10); //需要转成指针变量NSLog(@"%@ %d", person.name, person.age);

执行结果:

3.3 示例3

@interface ZSXPerson : NSObject@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *name;@end
// 成员列表数量
unsigned int count;
Ivar *ivars = class_copyIvarList([ZSXPerson class], &count);
// 遍历打印成员变量
for (int i = 0; i < count; i++) {// 取出 i 位置的成员变量Ivar ivar = ivars[i];NSLog(@"%s %s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));
}

执行结果:

@oubijiexi


http://www.mrgr.cn/p/80826227

相关文章

分类任务中的评估指标:Accuracy、Precision、Recall、F1

概念理解 T P TP TP、 T N TN TN、 F P FP FP、 F N FN FN精度/正确率&#xff08; A c c u r a c y Accuracy Accuracy&#xff09; 二分类查准率 P r e c i s i o n Precision Precision&#xff0c;查全率 R e c a l l Recall Recall 和 F 1 − s c o r e F1-score F1−s…

关于使用vscode搭建c/c++编程环境

目录 关于使用vscode搭建c/c编程环境一、前言二、安装 IDE 二、安装TDM-GCC安装三、安装C/C环境四、编写代码并进行编译 关于使用vscode搭建c/c编程环境 一、前言 一直觉得vscode是生产强有力的生产工具&#xff0c;基于此&#xff0c;做一篇学习笔记进行记录。 二、安装 ID…

怎样去保证 Redis 缓存与数据库双写一致性?

解决方案 那么我们这里列出来所有策略&#xff0c;并且讨论他们优劣性。 先更新数据库&#xff0c;后更新缓存先更新数据库&#xff0c;后删除缓存先更新缓存&#xff0c;后更新数据库先删除缓存&#xff0c;后更新数据库 先更新数据库&#xff0c;后更新缓存 这种方法是不推…

神策数据参与制定首份 SDK 网络安全国家标准

国家市场监督管理总局、国家标准化管理委员会发布中华人民共和国国家标准公告&#xff08;2023 年第 13 号&#xff09;&#xff0c;全国信息安全标准化技术委员会归口的 3 项国家标准正式发布。其中&#xff0c;首份 SDK 国家标准《信息安全技术 移动互联网应用程序&#xff0…

Ubuntu20.04更换镜像源------最简单的教程

本教程适用于&#xff1a;Ubuntu22.04 操作流程 打开终端&#xff0c;运行以下命令&#xff1a; sudo sed -i "shttp://.*archive.ubuntu.comhttps://mirrors.tuna.tsinghua.edu.cng" /etc/apt/sources.list 运行后即完成更改。 如果找不到22.04的镜像&#xff…

uniapp h5 touch事件踩坑记录

场景&#xff1a;悬浮球功能 当我给悬浮球设置了 position: fixed; 然后监听悬浮球的touch事件&#xff0c;从事件对象中拿到clientY和clientX赋值给悬浮球的left和top属性。当直接赋值后效果应该是这样子&#xff1a; 注意鼠标相对悬浮球的位置&#xff0c;应该就是左上角&a…

【氮化镓】位错对氮化镓(GaN)电子能量损失谱(EEL)的影响

本文献《Influence of dislocations on electron energy-loss spectra in gallium nitride》由C. J. Fall等人撰写&#xff0c;发表于2002年。研究团队通过第一性原理计算&#xff0c;探讨了位错对氮化镓&#xff08;GaN&#xff09;电子能量损失谱&#xff08;EEL&#xff09;…

CSS(二)---【常见属性、复合属性使用】

零.前言 本篇文章主要阐述CSS常见属性、复合属性&#xff0c;更多前置知识请见作者其它文章&#xff1a; CSS(一)---【CSS简介、导入方式、八种选择器、优先级】-CSDN博客 1.CSS属性 CSS的属性有上百个&#xff0c;但是我们并不需要全部学习&#xff0c;只要我们学习一部分…

分布式处理

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;这是我作为学习笔记原理篇的最后一章&#xff0c;一台计算机在数据中心里是不够的。因为如果只有一台计算机&#xff0c;我们会遇到三个核心问题。第一个核心问题&#xff0c;叫作垂直扩展和水平扩展的选择问题&#xff0c;…

数据库中的约束纯干货——主键约束

目录 &#xff08;一&#xff09;特点&#xff1a; &#xff08;二&#xff09;添加主键约束 2.1格式&#xff1a; 2.2举例&#xff1a; 2.3建立表级约束&#xff1a; 2.4建立表后增加主键约束 &#xff08;三&#xff09;复合主键 3.1格式&#xff1a; 3.2举例&#…

蓝桥杯真题Day40 倒计时19天 纯练题!

蓝桥杯第十三届省赛真题-统计子矩阵 题目描述 给定一个 N M 的矩阵 A&#xff0c;请你统计有多少个子矩阵 (最小 1 1&#xff0c;最大 N M) 满足子矩阵中所有数的和不超过给定的整数 K? 输入格式 第一行包含三个整数 N, M 和 K. 之后 N 行每行包含 M 个整数&#xf…

利用python搭建临时文件传输服务

场景 如果想从一台服务器上传输文件又多种方法&#xff0c;其中常见的是利用scp进行传输&#xff0c;但是需要知道服务器的账号密码才能进行传输&#xff0c;但有时候我们并不知道账号密码&#xff0c;这个时候我们就可以通过python -m SimpleHTTPServer 命令进行传输文件 启…

[ Linux ] git工具的基本使用(仓库的构建,提交)

1.安装git yum install -y git 2.打开Gitee&#xff0c;创建你的远程仓库&#xff0c;根据提示初始化本地仓库&#xff08;这里以我的仓库为例&#xff09; 新建好仓库之后跟着网页的提示初始化便可以了 3.add、commit、push三板斧 git add . //add仓库新增&#xff08;变…

前端Web移动端学习day05

移动 Web 第五天 响应式布局方案 媒体查询Bootstrap框架 响应式网页指的是一套代码适配多端&#xff0c;一套代码适配各种大小的屏幕。 共有两种方案可以实现响应式网页&#xff0c;一种是媒体查询&#xff0c;另一种是使用bootstrap框架。 01-媒体查询 基本写法 max-wid…

Linux系统使用Docker部署Portainer结合内网穿透实现远程管理容器和镜像

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

放弃 Rust 选择 Zig,Xata 团队推出 pgzx —— 计划使用 Zig 开发基于 PG 的分布式数据库

Summary Xata 公司在基于 PostgresSQL 开发自己的分布式数据库&#xff0c;出于 Zig 和 C 语言以及 PostgreSQL 的 API 有更好的互操作性的考虑&#xff0c;他们选择了 Zig 而非当红炸子鸡语言 Rust。他们的博客文章中对 pgzx 进行了介绍。让我们来看下他们对 Zig 和 Rust 语言…

Qt消息机制和事件

Qt消息机制和事件 Qt消息机制和事件--2 事件 事件&#xff08;event&#xff09;是由系统或者 Qt 本身在不同的时刻发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口需要重新绘制的时候&#xff0c;都会发出一个相应的事件。一些事件在对用户操作做出响应时发出&…

IP组播基础

原理概述 IANA ( Internet Assigned Numbers Authority &#xff09;将 IP 地址分成了 A 、 B 、 C 、 D 、 E5类&#xff0c;其中的 D 类为组播 IP 地址&#xff0c;范围是224.0.0.0~239.255.255.255。 一个 IP 报文&#xff0c;其目的地址如果是单播 IP 地址&#xff…

MLIR多层中间表示——用MLIR构建编译器(中)

1.3. 玩具语言IR方言 玩具语言方言:方言 在TableGen中声明性指定 def Toy_Dialect : Dialect {let summary = Toy IR Dialect;let description = [{这是对玩具语言方言的一个更长的描述...}];// 方言的命名空间.let name = toy;// 方言类定义所在的C++命名空间let cppNamespac…

Gitlab的流水线任务【实现每小时自动测试 dev分支的更新】

背景 在现代软件开发实践中&#xff0c;持续集成&#xff08;Continuous Integration, CI&#xff09;是确保代码质量和快速响应软件缺陷的关键策略。GitLab 提供了强大的 CI/CD 功能&#xff0c;允许开发者自动化测试和部署流程。本文将介绍如何设置 GitLab 流水线计划任务&a…