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

iOS高级理论:Runtime应用

一、遍历类的属性,快速归档

在 iOS 中,可以使用 Runtime 遍历类的属性来实现快速的归档(Archiving)操作。归档是将对象转换为数据流以便存储或传输的过程。下面是一个简单的示例,展示如何使用 Runtime 遍历类的属性进行归档操作:

假设有一个名为 Person 的类,我们想要对其属性进行归档操作:

#import <objc/runtime.h>@interface Person : NSObject <NSCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;
@end@implementation Person- (void)encodeWithCoder:(NSCoder *)coder {unsigned int count;objc_property_t *properties = class_copyPropertyList([self class], &count);for (int i = 0; i < count; i++) {objc_property_t property = properties[i];NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];id propertyValue = [self valueForKey:propertyName];[coder encodeObject:propertyValue forKey:propertyName];}free(properties);
}- (instancetype)initWithCoder:(NSCoder *)coder {self = [super init];if (self) {unsigned int count;objc_property_t *properties = class_copyPropertyList([self class], &count);for (int i = 0; i < count; i++) {objc_property_t property = properties[i];NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];id propertyValue = [coder decodeObjectForKey:propertyName];[self setValue:propertyValue forKey:propertyName];}free(properties);}return self;
}@end

在上面的示例中,encodeWithCoder: 方法遍历了 Person 类的所有属性,并将属性的值使用 NSCoder 进行归桋操作。initWithCoder: 方法则对归档的数据进行解档,恢复对象的状态。

通过使用 Runtime 遍历类的属性,我们可以实现一个通用的归档和解档方法,而无需手动编写大量的归档代码。这样可以提高代码的复用性和可维护性。

二、字典转模型

1、创建一个NSObject的分类

@interface NSObject (Json)
+ (instancetype)dictToModel:(NSDictionary *)dict;
@end

2、实现分类中字典转模型的方法

#import "NSObject+Json.h"
#import <objc/runtime.h>@implementation NSObject (Json)+ (instancetype)dictToModel:(NSDictionary *)dict
{id obj = [[self alloc] init];unsigned int count = 0;Ivar *ivars = class_copyIvarList([self class], &count);for (int i=0; i<count; i++) {Ivar ivar = ivars[i];NSMutableString *name = [NSMutableString stringWithUTF8String:ivar_getName(ivar)];[name deleteCharactersInRange:NSMakeRange(0, 1)];        [obj setValue:dict[name] forKey:name];}return obj;
}
@end

3、调用字典转模型的方法

- (void)viewDidLoad {[super viewDidLoad];NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];[dict setObject:@"张三" forKey:@"name"];[dict setObject:@"20" forKey:@"age"];[dict setObject:@"北京" forKey:@"address"];Student *student = [Student dictToModel:dict];NSLog(@"name:%@\n",student.name);NSLog(@"age:%@\n",student.age);NSLog(@"address:%@\n",student.address);
}

4、运行结果

2019-04-13 10:51:32.136568+0800 AppLife[19195:4640916] name:张三
2019-04-13 10:51:32.136707+0800 AppLife[19195:4640916] age:20
2019-04-13 10:51:32.136803+0800 AppLife[19195:4640916] address:北京

三 防止数组插入空值

1、创建一个NSMutableArray的分类

@interface NSMutableArray (Extension)@end

2、实现分类中方法的交换

#import "NSMutableArray+Extension.h"
#import <objc/runtime.h>@implementation NSMutableArray (Extension)+ (void)load {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{Class cls = NSClassFromString(@"__NSArrayM");Method method1 = class_getInstanceMethod(cls, @selector(insertObject:atIndex:));Method method2 = class_getInstanceMethod(cls, @selector(cs_insertObject:atIndex:));method_exchangeImplementations(method1, method2);});
}- (void)cs_insertObject:(id)anObject atIndex:(NSUInteger)index {if (anObject == nil) {return;}[self cs_insertObject:anObject atIndex:index];
}@end

3、调用

#import "NSMutableArray+Extension.h"
#import <objc/runtime.h>@implementation NSMutableArray (Extension)+ (void)load {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{Class cls = NSClassFromString(@"__NSArrayM");Method method1 = class_getInstanceMethod(cls, @selector(insertObject:atIndex:));Method method2 = class_getInstanceMethod(cls, @selector(cs_insertObject:atIndex:));method_exchangeImplementations(method1, method2);});
}- (void)cs_insertObject:(id)anObject atIndex:(NSUInteger)index {if (anObject == nil) {return;}[self cs_insertObject:anObject atIndex:index];
}@end

4、运行结果

2019-04-13 11:24:19.562363+0800 AppLife[20661:4661256] (Test
)

运用Rutime中交换方法的思想,还可以实现拦截所有按钮的点击时间和防止字典中插入空值等。

四、给分类添加属性

1、在分类里声明一个属性

#import "Student.h"@interface Student (Test)
@property (nonatomic, copy) NSString *englishName;
@end

2、实现get和set方法

@implementation Student (Test)- (void)setEnglishName:(NSString *)englishName
{// 第一个参数:给哪个对象添加关联// 第二个参数:关联的key,通过这个key获取// 第三个参数:关联的value// 第四个参数:关联的策略objc_setAssociatedObject(self, @"EnglishName", englishName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}- (NSString *)englishName
{return objc_getAssociatedObject(self, @"EnglishName");
}@end

五、其他

(1) 实现第一个场景:跟踪程序每个ViewController展示给用户的次数,可以通过Method Swizzling替换ViewDidAppear初始方法。创建一个UIViewController的分类,重写自定义的ViewDidAppear方法,并在其+load方法中实现ViewDidAppear方法的交换。

(2) 开发中常需要在不改变某个类的前提下为其添加一个新的属性,尤其是为系统的类添加新的属性,这个时候就可以利用Runtime的关联对象(Associated Objects)来为分类添加新的属性了。

(3) 实现字典的模型和自动转换,优秀的JSON转模型第三方库JSONModel、YYModel等都利用runtime对属性进行获取,赋值等操作,要比KVC进行模型转换更加强大,更有效率。阅读YYModel的源码可以看出,YY大神对NSObject的内容进行了又一次封装,添加了许多描述内容。其中YYClassInfo是对Class进行了再次封装,而YYClassIvarInfo、YYClassMethodInfo、YYClPropertyInfo分别是对Class的Ivar、Method和property进行了封装和描述。在提取Class的相关信息时都运用了Runtime。

相关文章:

iOS高级理论:Runtime应用

一、遍历类的属性&#xff0c;快速归档 在 iOS 中&#xff0c;可以使用 Runtime 遍历类的属性来实现快速的归档&#xff08;Archiving&#xff09;操作。归档是将对象转换为数据流以便存储或传输的过程。下面是一个简单的示例&#xff0c;展示如何使用 Runtime 遍历类的属性进…...

php判断和过滤get或者post的html标签,防止跨站点脚本(XSS),链接注入,框架注入等攻击

大部分网站都包含搜索功能&#xff0c;根据用户搜索的词去执行服务端的业务逻辑。如果一些黑客在搜索参数包含链接&#xff08;a&#xff09;、嵌入其他网页&#xff08;iframe&#xff09;、前端代码&#xff08;script&#xff09;等html字符&#xff0c;再加上服务端php不加…...

PySide6实现课堂点名程序

目录 一:实现思路 二:实现代码 三:完整代码和界面 一:实现思路 为了创建一点名程序,并编写一个基本的 GUI 应用程序。新建一个窗口,展在窗口界面添加开始和停止按钮的QPushButton,和展示正在显示的人名QLabel,点击开始时随机显示人名列表中的一个名字并且展示在QLab…...

瑞_Redis_Redis命令

文章目录 1 Redis命令Redis数据结构Redis 的 key 的层级结构1.0 Redis通用命令1.0.1 KEYS1.0.2 DEL1.0.3 EXISTS1.0.4 EXPIRE1.0.5 TTL 1.1 String类型1.1.0 String类型的常见命令1.1.1 SET 和 GET1.1.2 MSET 和 MGET1.1.3 INCR和INCRBY和DECY1.1.4 SETNX1.1.5 SETEX 1.2 Hash类…...

js 算法题 在数组中找出和为目标值 target 的那 两个 整数,并返回它们的数组下标

题目&#xff1a;给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以…...

基于springboot接口的编写

目录 1、模糊分页查询 2、批量删除 3、新增 4、编辑 此接口非彼接口。此接口是MVC的设计模式中的Controller层&#xff0c;一般我们会叫Controller层里的方法为接口。他们是负责接收前端或者其它服务的传来的请求&#xff0c;并对请求进行相应的处理&#xff0c;最终再将处…...

【HarmonyOS】鸿蒙开发之Video组件——第3.7章

Video组件内VideoOptions属性简介 src&#xff1a;设置视频地址。currentProgressRate&#xff1a;设置视频播放倍速&#xff0c;参数说明如下&#xff1a; number|string&#xff1a;只支持 0.75 &#xff0c; 1.0 &#xff0c; 1.25 &#xff0c; 1.75 &#xff0c; 2.0 。P…...

React引入css的几种方式以及应用

1.直接引入css文件 import "./parent.css" 2.引入css模块&#xff0c;定义文件名[组件名.module.css]&#xff1b;该方式可避免类名的重复&#xff0c;每个组件都有独立的作用域&#xff0c;避免了全局污染&#xff0c;保证了类名的唯一性 import styles from &qu…...

[算法沉淀记录] 排序算法 —— 冒泡排序

排序算法 —— 冒泡排序 基本概念 冒泡排序是一种简单的排序算法。它重复地遍历要排序的列表&#xff0c;一次比较两个元素&#xff0c;并交换它们的位置&#xff0c;如果它们不是按照升序排列的。这步遍历是重复进行的&#xff0c;直到没有再需要交换&#xff0c;也就是说该…...

【机器人最短路径规划问题(栅格地图)】基于遗传算法求解

基于遗传算法求解机器人最短路径规划问题&#xff08;栅格地图&#xff09;的仿真结果 仿真结果&#xff1a; 路径长度的变化曲线&#xff1a; 遗传算法优化后的机器人避障路径&#xff1a;...

如何做代币分析:以 TRX 币为例

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;TRX 代币仪表板 &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币相关的数据…...

关于地址引用与值引用的坑

List<UserInfo> userInfoList new List<UserInfo>(); List<UserInfo> userInfoList_new new List<UserInfo>(userInfoList);userInfoList_new 与userInfoList 指的是相同的内存吗&#xff1f; 答&#xff1a; 在C#中&#xff0c;userInfoList_new …...

初谈软件工程(一)

我就读于兰州交通大学的软件工程专业。虽然在全国众多的985、211高校中&#xff0c;兰州交通大学可能并不显眼&#xff0c;似乎未能跻身这些所谓的“顶尖”行列就意味着不被认可。然而&#xff0c;在甘肃省的教育领域中&#xff0c;它无疑是一座璀璨的明珠&#xff0c;名列前茅…...

自动化开展思路

自动化开展思路 本人在公司一直从事自动化测试推进工作&#xff0c;最近在好友的邀请下去其就职的公司分享如何开展自动化测试&#xff01; 希望能帮其解决如下几个痛点&#xff1a; 1.上线周期长&#xff1b; 2.测试时间紧张&#xff0c;上线信心不足&#xff0c;测试覆盖…...

安装使用zookeeper

先去官网下载zookeeper&#xff1a;Apache ZooKeeper 直接进入bin目录&#xff0c;使用powerShell打开。 输入: ./zkServer.cmd 命令&#xff0c;启动zookeeper。 zookeeper一般需要配合Dubbo一起使用&#xff0c;作为注册中心使用&#xff0c;可以参考另一篇博客&#xf…...

nginx实现http反向代理及负载均衡

目录 一、代理概述 1、代理概念 1.1 正向代理&#xff08;Forward Proxy&#xff09; 1.2 反向代理&#xff08;Reverse Proxy&#xff09; 1.3 正向代理与反向代理的区别 2、同构代理与异构代理 2.1 同构代理 2.2 异构代理 2.3 同构代理与异构代理的区别 二、四层代…...

vue组件中data为什么必须是一个函数

查看本专栏目录 关于作者 还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#x…...

科技论文编写思路

科技论文编写思路 1.基本框架2.课题可行性评估1.研究目标和意义2.研究方法和技术3.可行性和可操作性4.风险和不确定性5.经济性和资源投入6.成果预期和评估 3.写作思路4.利用AI读论文5.实验流程 1.基本框架 IntroductionRelated worksMethodExperiment and analysisDiscussionC…...

Windows虚拟机克隆后修改SID

在日常使用VMware Workstation我们经常会去克隆一些Windows操作系统的虚拟机&#xff0c;克隆的虚拟机和源虚拟机的系统安全标识符&#xff08;Security Identifiers&#xff0c;SID&#xff09;相同&#xff0c;SID是标识用户、组和计算机账户的唯一的号码。 如果两台虚拟机都…...

前端架构: 脚手架工具rxjs的快速上手应用

rxjs rxjs 是一个异步的库和Promise是非常的相似 文档&#xff1a;https://www.npmjs.com/package/rxjs Weekly Downloads 44,474,389 (动态数据) 说明这个库也是非常的流行 安装 $ npm i -S rxjs 使用 import { range, filter, map } from rxjs;range(1, 200).pipe(filte…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

业务系统对接大模型的基础方案:架构设计与关键步骤

业务系统对接大模型&#xff1a;架构设计与关键步骤 在当今数字化转型的浪潮中&#xff0c;大语言模型&#xff08;LLM&#xff09;已成为企业提升业务效率和创新能力的关键技术之一。将大模型集成到业务系统中&#xff0c;不仅可以优化用户体验&#xff0c;还能为业务决策提供…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

leetcodeSQL解题:3564. 季节性销售分析

leetcodeSQL解题&#xff1a;3564. 季节性销售分析 题目&#xff1a; 表&#xff1a;sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

企业如何增强终端安全?

在数字化转型加速的今天&#xff0c;企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机&#xff0c;到工厂里的物联网设备、智能传感器&#xff0c;这些终端构成了企业与外部世界连接的 “神经末梢”。然而&#xff0c;随着远程办公的常态化和设备接入的爆炸式…...