在iOS开发的世界里,关联对象(Associated Objects)如同一位神秘的魔法师,能够在运行时为已有的类动态添加“属性”,打破了Category的存储限制。你是否曾经好奇,它是如何在运行时做到这一点的?本文将从Runtime源码的角度,带你深入挖掘关联对象的底层实现原理,揭开这一技术的神秘面纱。
要理解关联对象的底层原理,我们需要从Runtime提供的三个核心API开始:objc_setAssociatedObject
、objc_getAssociatedObject
和objc_removeAssociatedObjects
。这些API共同构成了关联对象技术的基础,它们分别负责关联对象的创建、访问和清理工作。
当你调用objc_setAssociatedObject
函数时,Runtime系统会执行一系列复杂的操作来确保关联对象被正确地存储和管理。这个过程涉及到内存管理、线程安全以及哈希表操作等多个关键环节。
void objc_setAssociatedObject(id object, void* key, id value, objc_AssociationPolicy policy) {
_object_set_associative_reference(object, key, value, policy);
}
在这个函数中,首先将对象包装成DisguisedPtr
,以避免ARC错误处理、提高哈希分布均匀性并防止逆向分析。然后将value
和policy
封装成一个ObjcAssociation
对象,并根据内存管理策略对value
执行retain
或copy
操作。
接下来,获取全局锁以确保线程安全,然后获取全局关联对象的哈希表。通过哈希表插入或替换键对应的关联值。如果是首次设置关联对象,还会修改isa
上的hasAssociatedObjects
字段为true
。
获取关联对象的值,是通过objc_getAssociatedObject
函数实现的。这个函数内部会调用_object_get_associative_reference
来完成实际的获取操作。
id objc_getAssociatedObject(id object, constvoid* key) {
return _object_get_associative_reference(object, key);
}
这个函数首先获取全局锁以确保线程安全,然后通过对象作为键在第一层哈希表中查找对应的内层哈希表。如果找到内层表,则使用键作为键在第二层哈希表中查找ObjcAssociation
对象。如果找到ObjcAssociation
对象,则根据其内存管理策略对value
执行retain
操作。最后将value
加入自动释放池并返回。
关联对象的移除有两种方式:移除单个关联值和移除所有关联值。对于单个关联值的移除,可以通过调用objc_setAssociatedObject
函数并将value
参数设置为nil
来实现。而移除所有关联值,则需要调用objc_removeAssociatedObjects
函数。
void objc_removeAssociatedObjects(id object) {
if(object && object->hasAssociatedObjects()) {
_object_remove_associations(object, false);
}
}
这个函数首先获取全局锁以确保线程安全,然后获取全局关联对象哈希表,获取对象对应的内层表,并遍历并释放所有的关联对象。特别注意,如果存在OBJC_ASSOCIATION_SYSTEM_OBJECT
类型的关联对象,需要将这些对象重新插入到内层表中,以确保它们能在最后被释放。
尽管关联对象为我们提供了强大的动态扩展能力,但在实际使用过程中仍需要注意以下几个关键点:
OBJC_ASSOCIATION_ASSIGN
,避免造成野指针崩溃。RETAIN/COPY
策略时要注意避免循环引用。关联对象技术为Category突破了存储限制,但也带来了额外的复杂性和性能开销。在实际开发中,应当根据具体场景权衡使用,合理使用这把“双刃剑”。通过深入理解关联对象的底层原理,你将能够在未来的开发中更加游刃有余地运用这一技术。
声明:
1、本博客不从事任何主机及服务器租赁业务,不参与任何交易,也绝非中介。博客内容仅记录博主个人感兴趣的服务器测评结果及一些服务器相关的优惠活动,信息均摘自网络或来自服务商主动提供;所以对本博客提及的内容不作直接、间接、法定、约定的保证,博客内容也不具备任何参考价值及引导作用,访问者需自行甄别。
2、访问本博客请务必遵守有关互联网的相关法律、规定与规则;不能利用本博客所提及的内容从事任何违法、违规操作;否则造成的一切后果由访问者自行承担。
3、未成年人及不能独立承担法律责任的个人及群体请勿访问本博客。
4、一旦您访问本博客,即表示您已经知晓并接受了以上声明通告。
本站资源仅供个人学习交流,请于下载后24小时内删除,不允许用于商业用途,否则法律问题自行承担。
Copyright 2005-2024 yuanmayuan.com 【源码园】 版权所有 备案信息
声明: 本站非腾讯QQ官方网站 所有软件和文章来自互联网 如有异议 请与本站联系 本站为非赢利性网站 不接受任何赞助和广告