iOS 关联对象 (objc_setAssociatedObject/objc_getAssociatedObject)

category分类中 @property 并不会自动生成实例变量以及存取方法,所以一般使用关联对象为已经存在的类添加 “属性”。使用 objc_getAssociatedObject 以及 objc_setAssociatedObject 来模拟属性的存取方法

在category使用关联对象前首先需要导入<objc/runtime.h>的头文件

#import <objc/runtime.h>
OC中提供的关联对象api
关联对象set方法
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,  id _Nullable value, objc_AssociationPolicy policy)

关联对象get方法
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)

移除关联的对象
objc_removeAssociatedObjects(id _Nonnull object)
参数意义
  • object 被关联的对象 也就是对象的主分支
  • key key值 , key与关联的对象是一一对应关系。必须全局唯一。通常使用方式有@selector(methodName) 关联方法对象 或 使用&自定义KEY(__bridge const void *)(自定义KEY )绑定自定义静态KEY值
  • value 要关联的对象或值
  • policy关联策略

objc_AssociationPolicy policy有五种关联策略,视同nonatomicstrong 等修饰符

/**
 * Policies related to associative references.
 * These are options to objc_setAssociatedObject()
 */
typedef OBJC_ENUM(uintptr_t, objc_AssociationPolicy) {
    OBJC_ASSOCIATION_ASSIGN = 0,           /**< Specifies a weak reference to the associated object. */
    OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, /**< Specifies a strong reference to the associated object. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_COPY_NONATOMIC = 3,   /**< Specifies that the associated object is copied. 
                                            *   The association is not made atomically. */
    OBJC_ASSOCIATION_RETAIN = 01401,       /**< Specifies a strong reference to the associated object.
                                            *   The association is made atomically. */
    OBJC_ASSOCIATION_COPY = 01403          /**< Specifies that the associated object is copied.
                                            *   The association is made atomically. */
};
关联策略 objc_AssociationPolicy policy 等同的修饰符
OBJC_ASSOCIATION_ASSIGN @property(weak)
OBJC_ASSOCIATION_RETAIN_NONATOMIC @property(strong, nonatomic)
OBJC_ASSOCIATION_COPY_NONATOMIC @property(copy, nonatomic)
OBJC_ASSOCIATION_RETAIN @property(strong,atomic)
OBJC_ASSOCIATION_COPY @property(copy, atomic)

示例代码

#import <objc/runtime.h>

@implementation UITextField (LengthLimit)

static NSString *kLimitTextLengthKey = @"kLimitTextLengthKey";

- (void)setMaxLength:(int)length {
    objc_setAssociatedObject(self, (__bridge const void *)(kLimitTextLengthKey), [NSNumber numberWithInt:length], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    [self addTarget:self action:@selector(textFieldMaxLengthLimit:) forControlEvents:UIControlEventEditingChanged];
}



- (void)textFieldMaxLengthLimit:(id)textField {
    NSNumber *lengthNumber = objc_getAssociatedObject(self, (__bridge const void *)(kLimitTextLengthKey));
    int maxLength = [lengthNumber intValue];
}

_cmd 相关

_cmd 在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例。

cmd的作用域只在当前方法里,直指当前方法名@selector

#import "NSObject+AssociatedObject.h"
#import <objc/runtime.h>

@implementation NSObject (AssociatedObject)

- (void)setAssociatedObject:(id)associatedObject {
    objc_setAssociatedObject(self, @selector(associatedObject), associatedObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id)associatedObject {
    return objc_getAssociatedObject(self, @selector(associatedObject));
}

这里使用_cmd替换如下方式  二者是同意义
- (id)associatedObject {
    return objc_getAssociatedObject(self, _cmd);
}

@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。