Category 是否可以增加新的成员变数或属性?
因为Objective-C 物件会被编译成C 的structure,我们虽然可以在category中增加新的method,但是我们却不能够增加新的成员变数。
在Mac OS X 10.6 与iOS 4 之后,苹果提出一套叫做Associated Objects的办法,让我们可以在category 中增加新的getter/setter,观念差不多是:既然我们可以用一张表格记录一个class 有哪些method ,那,我们不就也可以另外建一张表格,记录有哪些实例与这个class相关?
要使用Associated Objects,我们需要引入objc/runtime.h
,然后调用objc_setAssociatedObject
建立setter,用getAssociatedObject
建立getter,调用时要传入:我们要让哪个实例与哪个实例之间建立关连,关连时使用的是哪一个key(类型为C字符串)。在以下的范例中,我们在MyCategory
这个category里,增加一个叫做myVar的property。
#import <objc/runtime.h>
@interface MyClass(MyCategory)
@property (retain, nonatomic) NSString *myVar;
@end
@implementation MyClass
- (void)setMyVar:(NSString *)inMyVar
{
objc_setAssociatedObject(self, "myVar",
inMyVar, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)myVar
{
return objc_getAssociatedObject(self, "myVar");
}
@end
在setMyVar:
中调用objc_setAssociatedObject
时,所最后一个参数OBJC_ASSOCIATION_RETAIN_NONATOMIC
,是用来决定要用哪一种内存管理策略,管理我们传入的参数,在我们的例子中,我们传入的是NSString
,是一个Objective-C实例,所以我们必须要retain是引用计数器加一。这边可以传入的参数还可以是OBJC_ASSOCIATION_ASSIGN
、OBJC_ASSOCIATION_COPY_NONATOMIC
、OBJC_ASSOCIATION_RETAIN
以及OBJC_ASSOCIATION_COPY
,与property语法使用的记忆体管理方式一致。而当我们的MyClass
物件在dealloc的时候,所有透过objc_setAssociatedObject
而retain起来的实例,也都会被一并释放。
虽然我们不能在category 中增加成员变数,但是却可以在extensions中定义。在Xcode 4.2 之后,我们可以这么写:
@interface MyClass()
{
NSString *myVar;
}
@end
我们甚至可以将成员变量直接放在@implementation
的代码块中:
@implementation MyClass
{
NSString *myVar;
}
@end