OC利用宏给category添加属性
Objective-C中,我们添加一个属性,需要利用runtime,调用setAssociateValue和getAssociatedValueForKey方法进行setter和getter方法的实现。但每次都要写上属性声明和方法实现,而且都是几乎一样的代码,只是类型稍有不同。所以我们是不是可以试着将这样的方法统一实现呢?
注:## 可以将前后的串进行拼接,# 可以将其后的数据转换成串。
1.既然是给类别(category)添加属性,当然还是要引入runtime的。
#import <objc/runtime.h>
2.实现代码
#define st_property_object(__type, __name) \
property (nonatomic, strong, setter=set__##__name:, getter=__##__name) __type* __name;
#define st_property_object_method(__type, __name) \
- (__type *)__##__name \
{\
return objc_getAssociatedObject(self, #__name);\
}\
\
- (void)set__##__name:(__type *)__##__name \
{\
objc_setAssociatedObject(self, #__name, __##__name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);\
}
这部分代码可以给category添加对象属性,但是如果是基础数据类型(如int,BOOL),就必须使用NSNumber了,这样在使用上也有一点不方便,故我们还需要增加一个基础数据类型的属性添加。如下:
#define st_metamacro_concat(A, B) st_metamacro_concat_(A, B)
#define st_metamacro_concat_(A, B) A##B
#define __st_BOOL_value(__number) [__number boolValue]
#define __st_int_value(__number) [__number intValue]
#define __st_NSInteger_value(__number) [__number integerValue]
#define __st_NSUInteger_value(__number) [__number unsignedIntegerValue]
#define __st_float_value(__number) [__number floatValue]
#define __st_CGFloat_value(__number) [__number floatValue]
#define __st_double_value(__number) [__number doubleValue]
#define st_property_basicDataType(__type, __name) \
property (nonatomic, assign, setter=set__##__name:, getter=__##__name) __type __name;
#define st_property_basicDataType_method(__type, __name) \
- (__type)__##__name \
{\
NSNumber *number = objc_getAssociatedObject(self, #__name);\
return st_metamacro_concat(st_metamacro_concat(__st_, __type), _value)(number);\
}\
\
- (void)set__##__name:(__type)__##__name \
{\
objc_setAssociatedObject(self, #__name, @(__##__name), OBJC_ASSOCIATION_RETAIN_NONATOMIC);\
}
-
代码理解
类对象的属性添加仅仅是getAssociatedValueForKey和setAssociateValue实现了getter和setter方法。而基础数据类型的属性添加,多了一个类型转换。实现转换的核心代码:
st_metamacro_concat(st_metamacro_concat(__st_, __type), _value)(number)
st_metamacro_concat宏实现了拼接功能,如st_metamacro_concat(_st, __type)的__type如果是NSInteger,那么拼接的结果就是__st_NSInteger, 那么st_metamacro_concat(st_metamacro_concat(_st, __type), _value)(number)的结果就是__st_NSInteger_value(__number),也就是[__number integerValue]。 -
好了,现在就是调用了,首先尝试给NSObject添加一个属性,代码如下
@interface NSObject (AddProperty)
@st_property_object(NSMutableArray, st_observerInfos)
@st_property_basicDataType(NSInteger, age)
@end
然后调用属性方法的宏,实现setter和getter:
@implementation NSObject (AddProperty)
st_property_object_method(NSMutableArray, st_observerInfos)
st_property_basicDataType_method(NSInteger, age)
@end
是不是方便了很多呢?如有写的不对的地方,欢迎告知。