详细总结 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
- }
复制代码 关联对象的优点:
- 无需修改原类即可添加属性
- 支持各种属性特性(strong/weak/copy)
- 线程安全选项
- 运行时动态性
留意事项:
- 合理利用关联策略
- 留意内存管理
- 制止过度利用
- 思量性能影响
- 留意命名冲突
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |