iOS 关联对象 (objc_setAssociatedObje

2019-04-28  本文已影响0人  Singularity_Lee

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)
参数意义

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
上一篇 下一篇

猜你喜欢

热点阅读