深入学习Objective-C(二)理解 objc 关联对象 (Associated Objects)

Objective-C入门指南:从环境搭建到实战项目开发 面向对象编程是现代软件开发的核心范式之一,它通过封装、继承和多态等机制组织代码,提升可维护性和复用性。在iOS/macOS生态中,Objective-C作为基于C语言的面向对象语言,其独特的消息传递机制和动态运行时特性,为理解Cocoa Touch框架的底层原理提供了关键视角。掌握Objective-C不仅能帮助开发者深入理解iOS系统框架的设计哲学,还能有效维护和迭代大量存量项目代码,尤其是在处理内存管理、与C/C++库桥接以及调试经典崩溃场景时具有不可替代的价值。对于希望夯实iOS开发基础、进入中大型团 阅读详情

今天看了下 objc 2.0 引入的强大特性:关联对象,下面把我的理解与大家分享一下。

我们都知道,我们在普通的 objc 类中,一般我们都会把成员变量声明在@interface中,如果你想把成员变量暴露在头文件中,你可以把它声明在实现文件中,甚至你也可以放在类扩展的区域中,但是,你却不能在普通的类目中声明成员变量。因为普通的类目只是用来扩展方法的,不能用来扩展成员变量。

有些时候,我们在设计代码时,会把代码分离成很多个类目,这样方便代码的管理。如下所示:

对每种类型的 API 单独放在对应的类目中,在代码组织上就非常清晰。但是,现在有一个这样的问题,有时候,我们需要在类目中保存一些状态,可以使用成员变量的形式来实现,但是,这些状态又是相对独立的,只在这个类目中会被用到,其他的类目不会使用它。所以,我们想把这个成员变量隐藏在这个类目中,对于其他的类目,这个成员变量都不可见。

如果类目允许扩展成员变量的话,这个问题就很好解决,直接在类目的实现文件里声明一个成员变量即可。这样既能对外部隐藏这个成员变量,又能在这个类目中使用它。很完美的解决方案,但是不幸的是,objc 不允许在类目中扩展成员变量。所以你不得不在类的声明中声明需要的成员变量,而且还需要把它暴露出来,以使你的类目能够使用它。这样,随着类目越来越多,你不得不在类中声明越来越多原本需要对外隐藏的成员变量。

我们上面遇到的问题,在一定程度上可以使用关联对象来解决,稍后我们会看一个具体的例子。现在,我们先来看看关联对象的基本使用方法。

我们在使用关联对象时,主要会用到下面两个方法:

void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)

id objc_getAssociatedObject(id object, void *key)

我们通过代码来看看如何使用它:

NSURL *u1 = [NSURL URLWithString:@"blog.codingcoder.com"];
objc_setAssociatedObject(u1, @"u1key", @"s1assciated", OBJC_ASSOCIATION_COPY);

id get1 = objc_getAssociatedObject(u1, @"u1key");


NSURL *u2 = [NSURL URLWithString:@"u2"];
id get2 = objc_getAssociatedObject(u2, @"u1key");

objc_setAssociatedObject 就是把一个对象关联到另外一个对象上去,比如下面的代码就是把一个字符串@"XXXX"关联到对象u1上面。这样就类似于对象u1对象上多了一个成员变量。

objc_setAssociatedObject(u1, @"u1key", @"XXXX", OBJC_ASSOCIATION_COPY);

特别注意一点,这里的关联对象,是关联到某一个具体的对象的,并不是关联到类的。

NSURL *u2 = [NSURL URLWithString:@"u2"];
id get2 = objc_getAssociatedObject(u2, @"u1key");

上面的代码中,u2变量并没有关联一个对象,所以,你不能通过objc_getAssociatedObject获取一个值。

另外需要注意一点,对象和被关联对象的生命周期是相互独立的。

根据WWDC 2011, Session 322 (第36分钟左右)发布的内存销毁时间表,被关联的对象在生命周期内要比对象本身释放的晚很多。它们会在被 NSObject -dealloc 调用的 object_dispose() 方法中释放。

下面我们来看一个例子,相信 AFNetworking 这个类库大家应该都很熟悉。在这个类库中,有一个UIImageView+AFNetworking的类目。

我们看一下源码:

我们可以看到,它生命了一个私有属性af_imageRequestOperation,而它通过自定义 getter / setter 方法,使用objc_getAssociatedObject 和 objc_setAssociatedObject方法来达到类似与添加成员变量的目的,而这个变量对外部是完全隐藏的。所以,这也就解决了我们最开始描述的那个类目无法扩展成员变量的问题。

最后,需要注意的一点是,这种objc_setAssociatedObject的方式是运用了 objc runtime 的特性,它确实很强大,但是,相对应的,不正确的使用或者滥用 runtime 会带来比较麻烦的 bug。所以,只有在你确定必须要使用 runtime 特性时,而且你完全明白你这么做所带来的影响时,才使用这种特性。一定不要为了使用这种技术而使用它。

参考文章:



K8S搭建(centos)完整版 每个人都有惰性,但不断学习是好好生活的根本,共勉! 阅读详情

相关推荐

Python数据清洗实战:用RapidFuzz搞定模糊匹配(附完整代码示例)

本文详细介绍了在Python数据清洗中,如何利用RapidFuzz库高效解决字符模糊匹配难题。通过实战代码示例,演示了从处理拼写错误、格式不一致的脏数据,到构建实体对齐与记录去重的完整清洗管道,帮助开发者提升数据质量与处理效率。

pear55的博客 529

关联对象 AssociatedObject 完全解析

关注仓库,及时获得更新:iOS-Source-Code-Analyze Follow: Draveness · Github 我们在 iOS 开发中经常需要使用分类(Category),为已经存在的类添加属性的需求,但是使用 @property 并不能在分类中正确创建实例变量和存取方法。 不过,通过 Objective-C 运行时中的...

weixin_33971130的博客 272

RK3399跨楼层机器人:SLAM技术与商业应用解析

SLAM(即时定位与地图构建)技术是移动机器人自主导航的核心,通过激光雷达、视觉传感器等多源数据融合实现厘米级定位。RK3399作为高性能嵌入式平台,其六核架构和Mali GPU能高效处理SLAM算法与传感器数据。在商业场景中,这种技术组合可支撑机器人实现跨楼层物资配送、仓库盘点等复杂任务。以SLAMTEC Hermes平台为例,其模块化设计支持电梯控制集成,配合双深度相机和360°激光雷达,在医疗、物流等领域已实现12分钟平均配送效率和99.7%的识别准确率。

weixin_30376083的博客 618

AssociatedObject关联对象原理实现

介绍 关联对象(AssociatedObject)是Objective-C 2.0运行时的一个特性,允许开发者对已经存在的类在扩展中添加自定义的属性。在实际生产过程中,比较常用的方式是给分类(Category)添加成员变量。 例子 #import <objc/runtime.h> @interface NSObject (AssociatedObject) @property (n...

weixin_30611509的博客 294

保姆级教程:用Code Blocks搞定中科蓝讯AB5768E蓝牙音响SDK开发环境(附资源包)

本文提供了一份详细的Code Blocks配置指南,帮助开发者快速搭建中科蓝讯AB5768E蓝牙音响SDK开发环境。从工具链安装、环境配置到工程导入和调试技巧,涵盖全流程避坑要点,特别适合K12开发板初学者。附资源包下载,助您高效完成蓝牙音响开发。

weixin_28692817的博客 448

An工具介绍之摄像头

An工具介绍之摄像头

人生得意须尽欢 6185

C# + WPF调用Web Api 自制B站客户端

【代码】C# + WPF调用Web Api 自制B站客户端。

菜鸟程序员 2039

c#.net使用正则表达式验证文本中是否包含手机号码或电话号码?

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Collections; namespace RegularPhoneApp { class Program

码农 3584

探究Objective-C中关联对象原理

一、实际问题 1.提出问题 首先,一切都要从一个问题开始:在Objective-C中,能否在Category中为类添加属性及对应的实例变量? 该题的答案是:不能。 2.分析解答 为什么不能通过Category来为Objective-C的类添加属性及对应的实例变量呢?原因在于在编译完成之后,类的内存布局就已经确定了,如果此时为类添加实例变量,则会破坏已经确定的内存布局,这显然是不合理的。这一点,可以...

TuGeLe的博客 704

Changer: Feature Interaction Is What You Need forChange Detection

还有“交换“交互是一种完全不需要参数和计算的操作,它是通过交换空间或通道维度上的双时态特征映射来实现的,交换的特征在经过后续的卷积或令牌混合时进行混合。方法二:提出了两种简单的交互策略,AD和特征“交换”,大量的实验表明,它们可以极大地提高MetaChanger的性能,特别是特征“交换”,即使嵌入到复杂的网络中或应用于具有挑战性的数据集。在这里,我们用虚线勾勒本文的重点。这是变化检测任务的基本问题,双时相图像提供了同一地区在不同时间点的图像数据,通过对比这两个时间点的图像,我们可以检测出该地区的变化。

yokon的博客 1620

Matt Pocock Skills — AI 编码代理技能包介绍与使用指南

《Matt Pocock Skills:AI编码代理技能包指南》 摘要: Matt Pocock Skills是一套开源AI编码代理技能包,旨在解决AI辅助开发中的四大痛点:需求理解偏差、token浪费、代码质量差和架构腐化。该技能包包含多种实用工具:/grill-with-docs用于需求对齐,/tdd实现测试驱动开发,/diagnose提供规范化调试流程,/triage管理issue生命周期。核心思想包括:通过拷问式对齐确保需求理解一致,建立共享领域语言提高沟通效率,快速反馈闭环加速开发,以及持续架构维

qq_45859163的博客 2221

iOS 关联对象详解

在平时的工作中经常碰到给类别添加属性的操作,那么实现思路是怎么样的呢? 代码实现:新建一个Person类和Person+Text的类别 //Person 代码 #import <Foundation/Foundation.h> @interface Person : NSObject @property (assign, nonatomic) int age; @end //类别代...

muziyuting的博客 2129

1.47寸ST7789V3彩色TFT LCD嵌入式驱动详解

TFT LCD是嵌入式人机交互(HMI)的核心显示技术,其工作原理依赖于行列驱动、RGB像素寻址与伽马校正等模拟/数字协同机制。ST7789V3作为主流低功耗TFT控制器,支持SPI接口与16位RGB565数据格式,具备高兼容性与轻量级驱动优势。在资源受限的MCU平台(如ARM Cortex-M系列)上,结合RT-Thread设备驱动模型与QSPI硬件加速,可实现高效显存管理、Bresenham图形算法及GB2312中文字模渲染。典型应用场景涵盖便携设备状态屏、工业HMI面板与教育开发套件——本文以1.47

weixin_42599908的博客 123

从零手写 NSObject-Rx:用 Objective-C Runtime 实现自己的 rx.disposeBag 完整教程

在 RxSwift 开发中,`rx.disposeBag` 几乎是每个 iOS 工程师的"标配":它帮你管理订阅生命周期,在对象销毁时自动释放资源。可你是否好奇过,这个看似神奇的能力,其实只用了几十行代码?本教程将带你从零手写一个 NSObject-Rx 风格的扩展,用 Objective-C Runtime 的关联对象(Associated Objects)机制,实现属于自己的 `rx.disp

gitblog_00533的博客 1059

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Associated Objects

本文转自TracyYih的博客  原文翻译自NSHipster的文章Associated Objects。 #import   Objective-C开发者在遇到上面这条“咒语”相关的一些东西时,会不自觉的变的非常谨慎。一个主要原因是:弄乱Objective-C运行时可能会改变整个实现结构,因为所有的代码都是运行在它之上的。   一方面:中的函数可以给应用或者框架增加强大的

小号鱼头 453

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

深入理解UIActivityIndicator-for-SDWebImage源码:关联对象与异步操作的实现细节

UIActivityIndicator-for-SDWebImage是一个为SDWebImage图像加载库添加活动指示器的iOS扩展,通过简单的Category实现让UIImageView在异步加载网络图片时自动显示加载动画。这个轻量级工具解决了iOS开发中常见的用户体验问题,让开发者能够快速为图片加载过程添加视觉反馈。 ## 🔍 为什么需要UIActivityIndicator-for-SD

gitblog_00721的博客 149

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Objective-C入门指南:iOS开发基石与Swift混编实战

面向对象编程是现代软件开发的核心范式,它通过封装、继承和多态等机制组织代码。在iOS/macOS生态中,Objective-C作为C语言的超集,其独特的消息传递机制和动态运行时特性,构成了Cocoa和Cocoa Touch框架的设计哲学基础。理解Objective-C的原理,不仅能帮助开发者深入掌握内存管理、引用循环等底层机制,更能无缝对接海量存量代码库,提升解决复杂问题的能力。在实际工程中,掌握Objective-C与Swift的混编技巧,是维护大型项目、集成第三方库的关键。本文聚焦Objective-C

weixin_33881140的博客 470

UIView.cheetah是怎么实现的:关联对象与自定义属性动画扩展源码剖析

Cheetah 是一个基于 Swift 的 iOS 轻量级动画库,它通过一句 `view.cheetah.move(100, 0).run()` 就能驱动任意 UIView 属性做链式动画。今天我们就以 `UIView.cheetah` 这个入口为线索,剖析它背后的两个核心机制:**Objective-C 关联对象**(Associated Objects)与**自定义属性动画系统**,看懂它如何

gitblog_00752的博客 374

Objective-C Runtime 底层原理与工程实践指南

Objective-C Runtime 是 iOS 系统中支撑消息传递、动态类结构和运行时元编程的核心机制,其本质是一套基于 C 语言实现的、与编译器深度协同的运行时库。它通过 isa 指针、objc_class 结构体、methodLists 与 cache 等内存布局,实现方法查找、继承调度与消息转发。该机制赋予了 ARC 内存管理、KVO 属性监听、@objc 桥接等高级特性的底层能力,广泛应用于无侵入埋点、热修复、动态模块化等工程场景。深入理解 Runtime 不仅有助于精准定位 objc_msgS

weixin_42530458的博客 193

OC-范畴

范畴的主要目的是防止一个拥有众多方法的类太长可以将类中的方法分散在多个范畴中范畴属于类可以看作给类的方法分组。

qq_43535469的博客 240

UIScrollView-InfiniteScroll源码解析:揭秘iOS无限滚动实现原理

UIScrollView-InfiniteScroll是一个为iOS开发者提供的强大无限滚动解决方案,通过分类(Category)方式为UIScrollView及其子类(UITableView、UICollectionView)添加无缝加载更多数据的能力。本文将深入剖析其核心实现原理,帮助开发者理解如何优雅地实现这一常见功能。 ## 🚀 核心实现架构 该库采用分类(Category)设计模式

gitblog_00007的博客 422

MNTPullToReact源码解析:理解iOS手势交互库的实现原理

想要在iOS应用中实现炫酷的下拉交互效果吗?MNTPullToReact是一个革命性的iOS手势交互库,它将传统的下拉刷新功能扩展为多动作交互系统。本文将深入解析这个开源库的源码实现原理,帮助你理解如何构建优雅的手势交互体验。 ## 🎯 项目概述与核心功能 MNTPullToReact是一个基于UIControl的iOS手势交互库,它通过扩展UITableView和UIWebView,让开发

gitblog_00364的博客 890

iOS内存管理底层:引用计数、SideTable、自动释放池与weak指针完整拆解

引用计数是Objective-C对象生命周期的核心机制,每个对象通过整型计数器管理持有与释放,而底层真正保存计数的地方并非单一全局表,而是isa指针的extra_rc位段与SideTable哈希表共同协作。为解决循环引用和野指针问题,weak指针通过SideTable中的weak_table登记观察者,在对象dealloc时自动置nil,同时自动释放池以AutoreleasePoolPage双向链表的形式按层回退。理解这些底层原理,不仅能帮助开发者推断对象何时释放、为何崩溃,还能在实际工程中更好地运用ARC

weixin_34037515的博客 329

RainbowNavigation深度解析:iOS导航栏颜色动画的实现原理与技术细节

想要为你的iOS应用添加流畅的导航栏颜色动画效果吗?🌈 RainbowNavigation是一个专为iOS开发者设计的开源库,它能够让你在Push和Pop操作时轻松实现UINavigationBar背景色的平滑过渡动画。这个强大的工具不仅支持任意颜色变化,还能实现透明导航栏和状态栏颜色遮罩效果,让你的应用界面更加生动有趣。 ## 什么是RainbowNavigation?🤔 Rainbow

gitblog_00268的博客 914
上一篇: 深入学习Objective-C(一):揭开NSObject的面纱
下一篇: iOS开发---- iOS整体框架类图
「已注销」
博客等级 码龄12年 28粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值