【OC】为category添加weak属性

友友们都知道,分类当中是不能添加property的,因为运行时系统不会自动完成@synthesize,所以需要使用runtime的关联对象形式完成property。也就是这一对函数

/**
设置关联对象
param object : 添加属性的对象,通常填入self
param key : 关联对象的SEL
param value : 关联对象的值
param policy : 关联对象的内存管理修饰词
*/
objc_setAssociatedObject(id  _Nonnull object, const void * _Nonnull key, id  _Nullable value, objc_AssociationPolicy policy)/**
获取关联对象
param object : 添加了属性的对象,通常填入self
param key : 关联对象的SEL
return : 关联对象
*/
objc_getAssociatedObject(id  _Nonnull object, const void * _Nonnull key)

其中setAssociated方法中有一个类型为objc_AssociationPolicy的参数policy,是代表这个关联对象的修饰词。点进去看一下,是一个枚举,其中有五个值:

OBJC_ASSOCIATION_ASSIGN
OBJC_ASSOCIATION_RETAIN_NONATOMIC
OBJC_ASSOCIATION_COPY_NONATOMIC
OBJC_ASSOCIATION_RETAIN
OBJC_ASSOCIATION_COPY

有copy,有retain,还有assign,看起来足够用了。但是没有我们经常使用的weak修饰。weak属性在对象被释放掉的时候,系统会查找sideTable表将对应的weak指针设置为nil。这样即使我们错误地向它发送消息也不会报错,同时也不会发生循环引用的情况。

那我们能用assign代替它吗?assign属性在对象被释放的时候不会将指针置nil,所以如果我们误用会访问野指针造成崩溃。在关联对象中也是如此吗?
尝试一下。

//h文件
//简单创建一个NSObject的分类,命名为Person
//为这个分类添加一个property
@property (nonatomic, weak) NSObject *work;

进入m文件中进行属性关联的具体设置

-(void)setWork:(NSObject *)work{objc_setAssociatedObject(self,@selector(work), work, OBJC_ASSOCIATION_ASSIGN);
}-(NSObject *)work{objc_getAssociatedObject(self, @selector(work));
}

完成之后我们为这个分类的属性赋值

	NSObject *person = [NSObject new];//为weak属性赋值{NSObject * weakObj = [NSObject new];person.work = weakObj;NSLog(@"作用域里 - %@",person.work);}NSLog(@"作用域外 - %@",person.work);

打印结果如下:
作用域里 - <NSObject: 0x600002ebc060>

第二行打印报EXC_BAD_ACCESS错误

看来关联对象的assign修饰和属性一样,离开作用域之后对象销毁,assign指针成为野指针,所以我们还是要想办法完成weak修饰。

这里有几种方法,目前使用的先记录下来,有空将剩下的补全。

一、创建一个中间类。
为中间类添加一个weak修饰的属性。通过中间类对象持有weak属性-分类属性关联中间类对象的形式完成分类添加weak属性的功能。可能说的不太清楚,看代码就理解了。简单的很,封装成了两个方法。

//首先创建一个用来持有weak属性的继承自NSObject的中间类
@interface ZYWeakProxyObject : NSObject
@property (nonatomic, weak)  id weakObject;     ///<弱引用的属性
@end//需要在m文件有实现
@implementation ZYWeakProxyObject
@end

接着我们在分类中添加封装的两个方法

//h文件
/**
设置weak属性
param key : property的SEL
param value : property的值
*/
-(void)setWeakPropertyWithKey:(SEL)key Value:(id)value;/**
获取weak属性
param key : property的SEL
*/
-(id)getWeakPropertyWithKey:(SEL)key;//m文件
//设置weak属性
-(void)setWeakPropertyWithKey:(SEL)key Value:(id)value{//获取保存的关联对象ZYWeakProxyObject *weakProxyObj = objc_getAssociatedObject(self, key);//如果没有就创建一个if (!weakProxyObj) {weakProxyObj = [ZYWeakProxyObject new];}//为中间类的弱属性赋值weakProxyObj.weakObject = value;/**保存。这里注意保存的是中间类对象,associationPolicy是retain。让对象强引用中间类对象,中间类对象弱引用真正需要weak的对象。这样对象释放之后,中间类持有的弱引用也会被置nil不会引发崩溃。而对象强引用的中间类对象,也会在对象被dealloc的时候进入dispose将关联对象销毁,不会发生内存泄漏。*/objc_setAssociatedObject(self, key, weakProxyObj, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}//获取weak属性
-(id)getWeakPropertyWithKey:(SEL)key{//获取保存的关联对象ZYWeakProxyObject *weakProxyObj = objc_getAssociatedObject(self, key);//返回它持有的weak对象return weakProxyObj.weakObject;
}

调用的话也很简单,直接在setter/getter方法中调用对应方法传参就行。
再次运行测验一下,打印结果如下:

作用域里 - <NSObject: 0x600000d9c000>
作用域外 - (null)

二、使用OBJC_ASSOCIATION_ASSIGN 来实现弱引用,在释放事件里面再将其释放掉,进而实现weak功能。

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

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

相关文章

T200HSA单路SDI/HDMI+1路3.5音频高清万能采集卡

产品简介&#xff1a; 同三维T200HSA单路高清万能采集卡&#xff0c;可以采集1路SDI/HDMI高清信号1路3.5音频信号&#xff0c;卡上有1个是HDMI接口1个是SDI接口1个3.5音频口&#xff0c;配件有&#xff1a; 1个小档板&#xff0c;PCI-E2.0 X1&#xff0c;分辨率最高可以达到10…

机器学习模型评估之校准曲线

模型校准曲线&#xff08;Calibration Curve&#xff09;&#xff0c;也称为可靠性曲线&#xff08;Reliability Curve&#xff09;或概率校准曲线&#xff08;Probability Calibration Curve&#xff09;&#xff0c;是一种评估分类模型输出概率准确性的图形工具。它可以帮助我…

【python数据可视化】利用Python爬取天气数据并实现数据可视化,绘制天气轮播图

用Python爬虫抓取全年天气数据并绘制天气轮播图 一、运行结果&#xff1a; 二、代码展示&#xff1a; 由csv文件生成↓ 接下来是绘制天气轮播图 运行结果&#xff1a; 完整代码请看这里↓&#x1f447; 提醒制作这个项目你需要执行以下几个步骤&#xff1a; 确定数据源&#x…

OTN分层结构变成什么样了?

传统OTN的三层架构包括光传输段层&#xff08;OTS&#xff09;、光复用段层&#xff08;OMS&#xff09;和光通道层&#xff08;OCh&#xff09;&#xff0c;它们共同构成了OTN的三层结构。 其中&#xff1a; 光传输段层&#xff08;OTS&#xff09;&#xff1a;OTS是OTN中最高…

React是如何渲染元素和组件的

元素的概念 元素是构成 React 应用的最小单位。元素描述了你在屏幕上想看到的内容。React 元素是创建开销极小的普通对象。React DOM 会负责更新 DOM 来与 React 元素保持一致。 将一个元素渲染为 DOM 假设我们的 HTML 文件有一个根元素 <div>该节点内的所有内容都将由 …

鸿蒙 Web组件的生命周期(api10、11、12)

概述 开发者可以使用Web组件加载本地或者在线网页。 Web组件提供了丰富的组件生命周期回调接口&#xff0c;通过这些回调接口&#xff0c;开发者可以感知Web组件的生命周期状态变化&#xff0c;进行相关的业务处理。 Web组件的状态主要包括&#xff1a;Controller绑定到Web组…

力扣SQL50 平均售价 ifnull SUM 连表查询

Problem: 1251. 平均售价 &#x1f468;‍&#x1f3eb; 参考题解&#xff08;题目数据增强&#xff0c;代码只能过90%的点&#xff09; &#x1f37b; AC code SELECT p.product_id, ROUND(ifnull(SUM(units * price) / SUM(units), 0),2) AS average_price FROM prices a…

初学51单片机之数字秒表

不同数据类型间的相互转换 在C语言中&#xff0c;不同数据类型之间是可以混合运算的。当表达式中的数据类型不一致时&#xff0c;首先转换为同一类型&#xff0c;然后再进行计算。C语言有两种方式实现类型转换。一是自动类型转换&#xff0c;另外一种是强制类型转换。 转换的主…

2024GLEE生活暨教育(上海)博览会,8月20-22日,国家会展中心(上海)

2024GLEE生活暨教育(上海)博览会将于8月20-22日在中国国家会展中心&#xff08;上海&#xff09;举行&#xff0c;博览会总面积近万平方米&#xff0c;设有美好生活和教育产品两大主力展区&#xff0c;全面覆盖婴幼儿、学龄前、小学、初中、高中、大学、中年、老年各个年龄段的…

数据库复习重点

第一章通常涵盖数据库系统的基础概念&#xff0c;这里将概述数据库、数据库系统、数据库管理系统的基本概念&#xff0c;数据库系统的三级模式结构&#xff0c;以及数据模型的三要素。 基本概念 数据&#xff08;Data&#xff09;&#xff1a; 数据是描述事物的符号记录&#…

Nvidia Isaac Sim搭建仿真环境 入门教程 2024(4)

Nvidia Isaac Sim 入门教程 2024 版权信息 Copyright 2023-2024 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. …

银行数仓项目实战(六)--基础层(完成存款的明细表---宽表)

文章目录 熟悉业务模型设计梳理映射关系加工宽表测试提交 FDM基础层&#xff1a;根据主题&#xff08;需求&#xff09;&#xff0c;将源数据加工集成&#xff0c;形成业务明细表–宽表 熟悉业务 当我们的工作来到基础层&#xff0c;我们首先要做的是跟甲方沟通&#xff0c;要…

未完工数据和系统数据对比分析

select * FROM ( select a.db_close_systime AS a_db_close_systime, -- 订单关闭时间 u.db_close_systime AS u_db_close_systime, -- 订单关闭时间 COALESCE( u.db_close_systime,a.db_close_systime) AS db_close_systime_coalesced ,-- 取非空值的订单关闭时间 a.i…

Harmony设计模式-单例模式

Harmony设计模式-单例模式 前言 软件设计模式&#xff08;[Design pattern](https://baike.baidu.com/item/Design pattern/10186718?fromModulelemma_inlink)&#xff09;&#xff0c;又称设计模式&#xff0c;是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经…

动态网页制作技术

动态网页制作技术是一种利用脚本语言、数据库和服务器端程序来生成动态内容的网页技术。以下是常用的动态网页制作技术&#xff1a; 1.PHP&#xff1a;PHP是一种广泛使用的服务器端脚本语言&#xff0c;可以嵌入到HTML中&#xff0c;用于生成动态网页内容。它可以与各种数据库进…

使用Kafka框架发送和接收消息(Java示例)

Kafka是一个开源的分布式流处理平台&#xff0c;以其在大数据和实时处理领域的广泛应用而闻名。以下是Kafka的关键特性以及它在消息传输方面的优势&#xff1a; 高吞吐量与低延迟&#xff1a;Kafka能够每秒处理数百万条消息&#xff0c;具有极低的延迟&#xff0c;这使得它非常…

前端调试技巧

1、利用console打印日志 2、利用debugger关键字&#xff0c;浏览器f12调用到方法debugger处会断点住&#xff0c;可以利用浏览器调试工具查看变量 a.监视表达式可以添加想要观察的变量 b.调用堆栈可以观察方法调用链 3、xhr断点 请求地址包含v1.0/banner_theme/pagelist&a…

Spacedrive:一个开源的跨平台文件管理器

文章目录 Spacedrive简介1.1 什么是Spacedrive&#xff1f;1.2 Spacedrive的核心功能1.3 Spacedrive的开发状态 Spacedrive的功能与特点2.1 文件存储在哪里&#xff1f;2.2 与传统文件管理器的区别2.3 与云存储服务的区别2.4 跨设备文件管理2.5 文件分类与过滤 Spacedrive的技术…

中科大和字节AI视频生成CamTrol杀疯了!运动可控,效果惊艳!

大家好&#xff0c;我是阿潘&#xff0c;今年堪称视频生成的爆发的一年&#xff0c;sora 2024年2月15日发布&#xff0c;让全世界都震惊了。openai 有一次成为了行业标杆。从生成的效果来看&#xff0c;比起以往抽象的生成结果&#xff0c;有了巨大的提升。 今天和大家分享中科…

DevExpress WPF中文教程:Grid - 如何将更改发布到数据库(设计时)?

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…