给定的答案很好用,我的建议只是对其的扩展,避免了编写过多的样板代码。
为了避免为类别属性重复编写getter和setter方法,此答案引入了宏。此外,这些宏还简化了基本类型属性(例如int
或)的使用BOOL
。
没有宏的传统方法
传统上,您定义类别属性,例如
@interface MyClass (Category)
@property (strong, nonatomic) NSString *text;
@end
然后,您需要使用关联的对象和get选择器作为键来实现getter和setter方法(请参阅原始答案):
#import <objc/runtime.h>
@implementation MyClass (Category)
- (NSString *)text{
return objc_getAssociatedObject(self, @selector(text));
}
- (void)setText:(NSString *)text{
objc_setAssociatedObject(self, @selector(text), text, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
我建议的方法
现在,您将使用宏来编写:
@implementation MyClass (Category)
CATEGORY_PROPERTY_GET_SET(NSString*, text, setText:)
@end
宏定义如下:
#import <objc/runtime.h>
#define CATEGORY_PROPERTY_GET(type, property) - (type) property { return objc_getAssociatedObject(self, @selector(property)); }
#define CATEGORY_PROPERTY_SET(type, property, setter) - (void) setter (type) property { objc_setAssociatedObject(self, @selector(property), property, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
#define CATEGORY_PROPERTY_GET_SET(type, property, setter) CATEGORY_PROPERTY_GET(type, property) CATEGORY_PROPERTY_SET(type, property, setter)
#define CATEGORY_PROPERTY_GET_NSNUMBER_PRIMITIVE(type, property, valueSelector) - (type) property { return [objc_getAssociatedObject(self, @selector(property)) valueSelector]; }
#define CATEGORY_PROPERTY_SET_NSNUMBER_PRIMITIVE(type, property, setter, numberSelector) - (void) setter (type) property { objc_setAssociatedObject(self, @selector(property), [NSNumber numberSelector: property], OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
#define CATEGORY_PROPERTY_GET_UINT(property) CATEGORY_PROPERTY_GET_NSNUMBER_PRIMITIVE(unsigned int, property, unsignedIntValue)
#define CATEGORY_PROPERTY_SET_UINT(property, setter) CATEGORY_PROPERTY_SET_NSNUMBER_PRIMITIVE(unsigned int, property, setter, numberWithUnsignedInt)
#define CATEGORY_PROPERTY_GET_SET_UINT(property, setter) CATEGORY_PROPERTY_GET_UINT(property) CATEGORY_PROPERTY_SET_UINT(property, setter)
宏CATEGORY_PROPERTY_GET_SET
为给定属性添加了一个getter和setter方法。只读或只写属性将分别使用CATEGORY_PROPERTY_GET
和CATEGORY_PROPERTY_SET
宏。
原始类型需要更多注意
由于原始类型不是对象,因此上述宏包含一个unsigned int
用作属性类型的示例。它通过将整数值包装到一个NSNumber
对象中来实现。因此,它的用法类似于前面的示例:
@interface ...
@property unsigned int value;
@end
@implementation ...
CATEGORY_PROPERTY_GET_SET_UINT(value, setValue:)
@end
在此之后的图案,你可以简单地添加多个宏也支持signed int
,BOOL
等...
局限性
OBJC_ASSOCIATION_RETAIN_NONATOMIC
默认情况下,所有宏都在使用。
重构属性名称时,像App Code这样的IDE 当前无法识别设置者的名称。您需要自己重命名。