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

发布于 2024-10-06 18:52:31 字数 530 浏览 0 评论 0原文

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

@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

I have a category on an existing class that adds a property and a few methods to the class.

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

@property (nonatomic, retain) NSString *aProperty;

@end

In the implementation file, I want to release this property when the object is deallocated. However, if I declare dealloc in this class, it will override the dealloc from the original class from what I understand. What then is the proper way to release this aProperty when the object is deallocated?

@implementation AClass (ACategory)

@synthesize aProperty;

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

@end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

何时共饮酒 2024-10-13 18:52:31

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

  1. 您不能在类别中声明实例变量;使用最新的 Objective-C ABI,您可以在类扩展中声明新的实例变量 (@interface AClass () {//...),但这与类别 (@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

它的实现必须位于类的主@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。

Well, this is a little problematic, since your code is wrong.

  1. You can't declare instance variables in a category; using the latest Objective-C ABI, you can declare new instance variables within a class extension (@interface AClass () {//...), but that is different from a category (@interface AClass (ACategory)).
  2. Even if you could, the syntax for instance variable declaration is that they be enclosed in curly braces after the @interface line.

You can declare a property in a category, but you'll have to define its storage without using a new instance variable (hence, @dynamic instead of @synthesize).


As to your actual question, you can't call the original implementation of an overridden method unless you use method-swizzling (facilitated by runtime functions like method_exchangeImplementations). I recommend against doing this anyway; it's really frightening and dangerous.


Update: Explanation of Instance Variables in Class Extensions

A class extension is like a category, but it is anonymous and must be placed within the .m file associated with the original class. It looks like:

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

Its implementation must be in the main @implementation block for your class. Thus:

@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

So, a class extension is useful for keeping private instance variables and methods out of the public interface, but will not help you add instance variables to a class over which you haven't control. There is no issue with overriding -dealloc, because you just implement it like you normally would, whilst including any necessary memory management for the instance variables you introduced within the class extension.

Please note that this stuff works only with the latest 64-bit Objective-C ABI.

倾听心声的旋律 2024-10-13 18:52:31

顺便说一句,您可以使用关联引用来“模拟向现有类添加对象实例变量”。

本质上,您可以添加关联对象,如下所示:

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 文档为 此处

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

As an aside, you can use associated references to "simulate the addition of object instance variables to an existing class".

Essentially, you can add an associated object as below:

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);

And release the associated object by sending 'nil':

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

The Apple documentation is here.

It took me a while to find, so I hope that it helps someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文