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

Anu*_*rag 6 objective-c dealloc objective-c-category

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

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

@property (nonatomic, retain) NSString *aProperty;

@end
Run Code Online (Sandbox Code Playgroud)

在实现文件中,我想在取消分配对象时释放此属性.但是,如果我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
Run Code Online (Sandbox Code Playgroud)

Jon*_*ing 12

嗯,这有点问题,因为你的代码是错误的.

  1. 您不能在类别中声明实例变量; 使用最新的Objective-C ABI,您可以在类extension(@interface AClass () {//...)中声明新的实例变量,但这与category(@interface AClass (ACategory))不同.
  2. 即使你可以,实例变量声明的语法是@interface在行后面用花括号括起来.

您可以在类别中声明属性,但是您必须在不使用新实例变量的情况下定义其存储(因此,@dynamic而不是@synthesize).


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


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

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

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

它的实现必须@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
Run Code Online (Sandbox Code Playgroud)

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

请注意,这些东西仅适用于最新的64位Objective-C ABI.


pau*_*ore 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);
Run Code Online (Sandbox Code Playgroud)

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

// And release the associated object
objc_setAssociatedObject(self,
    &ASI_HTTP_REQUEST, 
    nil, 
    OBJC_ASSOCIATION_RETAIN);
Run Code Online (Sandbox Code Playgroud)

Apple文档在这里.

我花了一段时间才找到,所以我希望它有助于某人.