Objective-C释放在类别中声明的属性?

时间:2010-12-06 19:53:26

标签: objective-c dealloc objective-c-category

我在现有类上有一个类别,它为类添加了一个属性和一些方法。

@interface AClass (ACategory) {
    NSString *aProperty;
}

@property (nonatomic, retain) NSString *aProperty;

@end

在实现文件中,我想在取消分配对象时释放此属性。但是,如果我在这个类中声明dealloc,它将根据我的理解覆盖原始类的dealloc。当对象被解除分配时,释放此aProperty的正确方法是什么?

@implementation AClass (ACategory)

@synthesize aProperty;

- (void)dealloc {
    [aProperty release];
    // this will skip the original dealloc method from what I understand
    [super dealloc];
}

@end

2 个答案:

答案 0 :(得分:12)

嗯,这有点问题,因为你的代码错了。

  1. 您无法在类别中声明实例变量;使用最新的Objective-C ABI,您可以在类扩展(@interface AClass () {//...)中声明新的实例变量,但这与类别(@interface AClass (ACategory))不同。
  2. 即使可以,实例变量声明的语法是在@interface行之后用大括号括起来。
  3. 您可以在类别中声明属性,但是您必须在不使用新实例变量的情况下定义其存储(因此,@dynamic而不是@synthesize)。


    至于你的实际问题,你不能调用重写方法的原始实现,除非你使用方法调配(由method_exchangeImplementations等运行时函数促进)。无论如何,我建议不要这样做;这真是令人恐惧和危险。


    更新:类扩展中的实例变量的说明

    类扩展类似于类别,但它是匿名的,必须放在与原始类关联的.m文件中。它看起来像:

    @interface SomeClass () {
        // any extra instance variables you wish to add
    }
    @property (nonatomic, copy) NSString *aProperty;
    @end
    

    其实施 必须 位于您班级的主@implementation块中。因此:

    @implementation SomeClass
    // synthesize any properties from the original interface
    @synthesize aProperty;
    // this will synthesize an instance variable and accessors for aProperty,
    // which was declared in the class extension.
    - (void)dealloc {
        [aProperty release];
        // perform other memory management
        [super dealloc];
    }
    @end
    

    因此,类扩展对于将私有实例变量和方法保留在公共接口之外非常有用,但是无法帮助您将实例变量添加到您无法控制的类中。覆盖-dealloc没有问题,因为您只是像通常那样实现它,同时包括您在类扩展中引入的实例变量的任何必要的内存管理。

    请注意,此内容仅适用于最新的64位Objective-C ABI。

答案 1 :(得分:5)

另外,您可以使用关联引用来“模拟将对象实例变量添加到现有类”。

基本上,您可以添加如下关联对象:

static void* ASI_HTTP_REQUEST;  // declare inside the category @implementation but outside any method    

// And within a method, init perhaps
objc_setAssociatedObject(self, 
    &ASI_HTTP_REQUEST, 
    request, 
    OBJC_ASSOCIATION_RETAIN);

通过发送'nil'来释放相关对象:

// And release the associated object
objc_setAssociatedObject(self,
    &ASI_HTTP_REQUEST, 
    nil, 
    OBJC_ASSOCIATION_RETAIN);

Apple文档为here

我花了一段时间才找到,所以我希望它可以帮助别人。