在category分類中 @property 并不會(huì)自動(dòng)生成實(shí)例變量以及存取方法,所以一般使用關(guān)聯(lián)對(duì)象為已經(jīng)存在的類添加 “屬性”。使用 objc_getAssociatedObject 以及 objc_setAssociatedObject 來模擬屬性的存取方法
在category使用關(guān)聯(lián)對(duì)象前首先需要導(dǎo)入<objc/runtime.h>的頭文件
#import <objc/runtime.h>
OC中提供的關(guān)聯(lián)對(duì)象api
關(guān)聯(lián)對(duì)象set方法
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy)
關(guān)聯(lián)對(duì)象get方法
objc_getAssociatedObject(id _Nonnull object, const void * _Nonnull key)
移除關(guān)聯(lián)的對(duì)象
objc_removeAssociatedObjects(id _Nonnull object)
參數(shù)意義
-
object被關(guān)聯(lián)的對(duì)象 也就是對(duì)象的主分支 -
keykey值 , key與關(guān)聯(lián)的對(duì)象是一一對(duì)應(yīng)關(guān)系。必須全局唯一。通常使用方式有@selector(methodName)關(guān)聯(lián)方法對(duì)象 或 使用&自定義KEY或(__bridge const void *)(自定義KEY )綁定自定義靜態(tài)KEY值 -
value要關(guān)聯(lián)的對(duì)象或值 -
policy關(guān)聯(lián)策略
objc_AssociationPolicy policy有五種關(guān)聯(lián)策略,視同nonatomic 和 strong 等修飾符
/**
* 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. */
};
| 關(guān)聯(lián)策略 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 相關(guān)
_cmd 在Objective-C的方法中表示當(dāng)前方法的selector,正如同self表示當(dāng)前方法調(diào)用的對(duì)象實(shí)例。
cmd的作用域只在當(dāng)前方法里,直指當(dāng)前方法名@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