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_ASSIGNOBJC_ASSOCIATION_COPY_NONATOMICOBJC_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

results matching ""

    No results matching ""