iOS - 关联对象

详细总结 Objective-C 的关联对象功能:

1. 基本使用

// 1. 设置关联对象
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy);// 2. 获取关联对象
id objc_getAssociatedObject(id object, const void *key);// 3. 移除关联对象
objc_removeAssociatedObjects(id object);

2. 关联策略

typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {OBJC_ASSOCIATION_ASSIGN = 0,           // 弱引用OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, // 强引用,非原子OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   // 复制,非原子OBJC_ASSOCIATION_RETAIN = 01401,       // 强引用,原子OBJC_ASSOCIATION_COPY = 01403          // 复制,原子
};

3. 实现示例

3.1 分类中添加属性

// UIView+Extension.h
@interface UIView (Extension)
@property (nonatomic, strong) NSString *identifier;
@end// UIView+Extension.m
@implementation UIView (Extension)static void *IdentifierKey = &IdentifierKey;- (void)setIdentifier:(NSString *)identifier {objc_setAssociatedObject(self, IdentifierKey, identifier, OBJC_ASSOCIATION_COPY_NONATOMIC);
}- (NSString *)identifier {return objc_getAssociatedObject(self, IdentifierKey);
}@end

3.2 使用宏简化

// 定义关联属性的宏
#define OBJC_ASSOCIATION_PROPERTY_STRONG(_getter_, _setter_, _association_) \
- (void)_setter_:(id)object { \objc_setAssociatedObject(self, @selector(_getter_), object, _association_); \
} \
- (id)_getter_ { \return objc_getAssociatedObject(self, @selector(_getter_)); \
}// 使用宏
@implementation UIView (Extension)
OBJC_ASSOCIATION_PROPERTY_STRONG(identifier, setIdentifier, OBJC_ASSOCIATION_COPY_NONATOMIC)
@end

4. 关键点

4.1 Key 的选择

// 1. 静态变量地址
static char kAssociatedObjectKey;
objc_setAssociatedObject(obj, &kAssociatedObjectKey, value, policy);// 2. 选择器
objc_setAssociatedObject(obj, @selector(propertyName), value, policy);// 3. 字符串常量
static NSString *const kAssociatedKey = @"kAssociatedKey";
objc_setAssociatedObject(obj, (__bridge void *)kAssociatedKey, value, policy);

4.2 内存管理

// 强引用示例
objc_setAssociatedObject(self, @selector(strongProperty), object, OBJC_ASSOCIATION_RETAIN_NONATOMIC);// 弱引用示例
objc_setAssociatedObject(self, @selector(weakProperty), object, OBJC_ASSOCIATION_ASSIGN);

5. 线程安全

// 原子操作
objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN); // 使用带原子性的关联策略// 手动加锁
@synchronized(self) {objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

6. 最佳实践

6.1 属性封装

@interface NSObject (Associated)@property (nonatomic, strong) id associatedObject;
@property (nonatomic, weak) id weakAssociatedObject;
@property (nonatomic, copy) NSString *copyAssociatedObject;@end

6.2 清理处理

- (void)dealloc {// 移除特定关联对象objc_setAssociatedObject(self, @selector(associatedObject), nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);// 或移除所有关联对象objc_removeAssociatedObjects(self);
}

7. 注意事项

// 1. 避免循环引用
@implementation MyClass
- (void)setupBlock {__weak typeof(self) weakSelf = self;self.associatedBlock = ^{__strong typeof(weakSelf) strongSelf = weakSelf;[strongSelf doSomething];};
}// 2. 合理选择关联策略
- (void)setDelegate:(id<MyDelegate>)delegate {objc_setAssociatedObject(self, @selector(delegate), delegate, OBJC_ASSOCIATION_ASSIGN); // 代理使用 ASSIGN
}

关联对象的优点:

  1. 无需修改原类即可添加属性
  2. 支持各种属性特性(strong/weak/copy)
  3. 线程安全选项
  4. 运行时动态性

注意事项:

  1. 合理使用关联策略
  2. 注意内存管理
  3. 避免过度使用
  4. 考虑性能影响
  5. 注意命名冲突

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

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

相关文章

Web开发中页面出现乱码的解决(Java Web学习笔记:需在编译时用 -encoding utf-8)

目录 1 引言2 乱码表现、原因分析及解决2.1 乱码表现2.2 原因分析2.3 解决 3 总结 1 引言 Web开发的页面出现了乱码&#xff0c;一直不愿写出来&#xff0c;因为网上的解决方案太多了。但本文的所说的页面乱码问题&#xff0c;则是与网上的大多数解决方案不一样&#xff0c;使…

HarmonyOS:@LocalBuilder装饰器: 维持组件父子关系

一、前言 当开发者使用Builder做引用数据传递时&#xff0c;会考虑组件的父子关系&#xff0c;使用了bind(this)之后&#xff0c;组件的父子关系和状态管理的父子关系并不一致。为了解决组件的父子关系和状态管理的父子关系保持一致的问题&#xff0c;引入LocalBuilder装饰器。…

初学stm32 --- DAC输出三角波和正弦波

输出三角波实验简要&#xff1a; 1&#xff0c;功能描述 通过DAC1通道1(PA4)输出三角波&#xff0c;然后通过DS100示波器查看波形 2&#xff0c;关闭通道1触发(即自动) TEN1位置0 3&#xff0c;关闭输出缓冲 BOFF1位置1 4&#xff0c;使用12位右对齐模式 将数字量写入DAC_…

【opencv】第7章 图像变换

7.1 基 于OpenCV 的 边 缘 检 测 本节中&#xff0c;我们将一起学习OpenCV 中边缘检测的各种算子和滤波器——Canny 算子、Sobel 算 子 、Laplacian 算子以及Scharr 滤波器。 7.1.1 边缘检测的一般步骤 在具体介绍之前&#xff0c;先来一起看看边缘检测的一般步骤。 1.【第…

【Python】Python与C的区别

文章目录 语句结束符代码块表示变量声明函数定义注释格式Python的标识符数据输入input()函数数据输出print()函数 语句结束符 C 语言 C 语言中每条语句必须以分号;结束。例如&#xff0c;int a 10;、printf("Hello, World!");。分号是语句的一部分&#xff0c;用于…

web-app uniapp监测屏幕大小的变化对数组一行展示数据作相应处理

web-app uniapp监测屏幕大小的变化对数组一行展示数据作相应处理 1.uni.getSystemInfoSync().screenWidth; 获取屏幕宽度 2.uni.onWindowResize&#xff08;&#xff09; 实时监测屏幕宽度变化 3.根据宽度的大小拿到每行要展示的数量itemsPerRow 4.为了确保样式能够根据 items…

Idea-离线安装SonarLint插件地址

地址&#xff1a; SonarQube for IDE - IntelliJ IDEs Plugin | Marketplace 选择Install Plugin from Disk..&#xff0c;选中下载好的插件&#xff0c;然后重启idea

数据结构与算法之二叉树: LeetCode 637. 二叉树的层平均值 (Ts版)

二叉树的层平均值 https://leetcode.cn/problems/average-of-levels-in-binary-tree/description/ 描述 给定一个非空二叉树的根节点 root , 以数组的形式返回每一层节点的平均值与实际答案相差 1 0 − 5 10^{-5} 10−5 以内的答案可以被接受 示例 1 输入&#xff1a;root…

MySQL表的增删改查(基础)-下篇

修改 真正在改硬盘了&#xff0c;这样的修改是“持久有效”。一定要确保&#xff0c;update的修改是改对了&#xff0c;改出问题来就麻烦。指定update的时候&#xff0c;如果当前不指定任何条件&#xff0c;就会针对所有的行都能生效&#xff01; (把整个表都给改了)。 案例 --…

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(五)

文章目录 一、学生管理模块功能实现1、添加学生功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、学生管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码…

使用 WPF 和 C# 绘制图形

绘图困难 此示例展示了如何在 WPF 和 C# 中绘制图形。绘制图形总是很棘手&#xff0c;因为您通常需要在至少两个不同的坐标系中工作。首先&#xff0c;您要为图形使用世界坐标。例如&#xff0c;您可能希望 X 值的范围为 2000 年至 2020 年&#xff0c;Y 值的范围为 10,000 美元…

3D滤波器处理遥感tif图像

import cv2 import numpy as np from osgeo import gdal# 定义 Gabor 滤波器的参数 kSize 31 # 滤波器核的大小 g_sigma 3.0 # 高斯包络的标准差 g_theta np.pi / 4 # Gabor 函数的方向 g_lambda 10.0 # 正弦波的波长 g_gamma 0.5 # 空间纵横比 g_psi np.pi / 2 # …

JuiceFS 2024:开源与商业并进,迈向 AI 原生时代

即将过去的 2024 年&#xff0c;是 JuiceFS 开源版本推出的第 4 年&#xff0c;企业版的第 8 个年头。回顾过去这一年&#xff0c;JuiceFS 社区版依旧保持着快速成长的势头&#xff0c;GitHub 星标突破 11.1K&#xff0c;各项使用指标增长均超过 100%&#xff0c;其中文件系统总…

高可用虚拟IP-keepalived

个人觉得华为云这个文档十分详细&#xff1a;使用虚拟IP和Keepalived搭建高可用Web集群_弹性云服务器 ECS_华为云 应用场景&#xff1a;虚拟IP技术。虚拟IP&#xff0c;就是一个未分配给真实主机的IP&#xff0c;也就是说对外提供数据库服务器的主机除了有一个真实IP外还有一个…

支付宝租赁小程序提升租赁行业效率与用户体验

内容概要 在当今数字化的世界里&#xff0c;支付宝租赁小程序的出现构建了一种新的租赁模式&#xff0c;使得用户在使用过程中体验更加流畅。想象一下&#xff0c;你在寻找租赁服务时&#xff0c;不再需要繁琐的流程和冗长的等待&#xff0c;只需通过手机轻松点击几下&#xf…

python异常机制

异常是什么&#xff1f; 软件程序在运行过程中&#xff0c;非常可能遇到刚刚提到的这些问题&#xff0c;我们称之为异常&#xff0c;英文是Exception&#xff0c;意思是例外。遇到这些例外情况&#xff0c;或者交异常&#xff0c;我们怎么让写的程序做出合理的处理&#xff0c…

Git撤销指定commit并更新远端仓库

Git撤销指定commit并更新远端仓库 一、撤销指定commit 1.首先执行git log 命令&#xff0c;查看git历史提交以及commit信息&#xff1a; 由于需要脱敏&#xff0c;所以截图可能看得马赛克比较多&#xff0c;需要关注的就是上面的commit后跟的id&#xff0c;以及HEAD当前指定…

【opencv】第8章 图像轮廓与图像分割修复

8.1 查找并绘制轮廓 一个轮廓一般对应一系列的点&#xff0c;也就是图像中的一条曲线。其表示方法可能 根据不同的情况而有所不同。在OpenCV 中&#xff0c;可以用findContours()函数从二值图 像中查找轮廓 8.1.1 寻找轮廓&#xff1a; findContours() 函数 findContours) 函…

.NET Core NPOI 导出图片到Excel指定单元格并自适应宽度

NPOI&#xff1a;支持xlsx&#xff0c;.xls&#xff0c;版本>2.5.3 XLS&#xff1a;HSSFWorkbook&#xff0c;主要前缀HSS&#xff0c; XLSX&#xff1a;XSSFWorkbook&#xff0c;主要前缀XSS&#xff0c;using NPOI.XSSF.UserModel; 1、导出Excel添加图片效果&#xff0…

SQL分类与数据类型整理

SQL分类与数据类型整理 SQL分类数据类型数值型整数型小数型布尔型字符串型日期型二进制型其他类型&#xff08;空间数据类型&#xff09; 总结 SQL&#xff0c;全称为Structured Query Language&#xff08;结构化查询语言&#xff09;&#xff0c;是一种高度专业化的计算机语言…