通常在分类中只能声明方法,不能添加属性变量,但是其实可以通过关联对象(Objective-C Associated Objects)实现给分类添加属性的。
首先,给分类添加属性不会自动生成getter、setter方法,需要使用关联对象Runtime提供的这几个接口来实现。
//添加关联对象
void objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
//获取关联的对象
id objc_getAssociatedObject(id object, const void *key)
//移除关联的对象
void objc_removeAssociatedObjects(id object)
- 参数解释
id object:被关联的对象
const void *key:关联的key,要求唯一
id value:关联的对象
objc_AssociationPolicy policy:内存管理的策略
- 内存管理的策略
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_ASSOCIATION_ASSIGN | @property (assign) 或 @property (unsafe_unretained) | 指定一个关联对象的弱引用。 |
OBJC_ASSOCIATION_RETAIN_NONATOMIC | @property (nonatomic, strong) | 指定一个关联对象的强引用,不能被原子化使用。 |
OBJC_ASSOCIATION_COPY_NONATOMIC | @property (nonatomic, copy) | 指定一个关联对象的copy引用,不能被原子化使用。 |
OBJC_ASSOCIATION_RETAIN | @property (atomic, strong) | 指定一个关联对象的强引用,能被原子化使用。 |
OBJC_ASSOCIATION_COPY | @property (atomic, copy) | 指定一个关联对象的copy引用,能被原子化使用。 |
接下来,给UIView添加一个Color分类,并使用关联对象RunTime给UIView添加一个属性foregroundColor。
- 创建分类,在.h文件中添加属性。
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface UIView (Color)
@property (nonatomic, strong) UIColor *foregroundColor;
@end
NS_ASSUME_NONNULL_END
- 在.m文件中引入runtime头文件,需要添加一个关联对象时的用来标记对应的那个属性的key,为了保证这个key唯一不变,使用静态变量,有三种写法,效果是一样的。
//静态变量存储地址唯一不变
static NSString *kForegroundColorKey = @"kForegroundColorKey";
static void *kForegroundColorKey = &kForegroundColorKey;
static char kForegroundColorKey;
- 添加属性的getter、setter方法
#import "UIView+Color.h"
#import "objc/runtime.h"
@implementation UIView (Color)
static char kForegroundColorKey;
- (void)setForegroundColor:(UIColor *)foregroundColor{
objc_setAssociatedObject(self, &kForegroundColorKey, foregroundColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *)foregroundColor {
return objc_getAssociatedObject(self, &kForegroundColorKey);
}
@end
- 使用
UIView * view = [[UIView alloc]init];
view.foregroundColor = [UIColor whiteColor];
UIColor * color = view.foregroundColor;