6

クラスにプロパティといくつかのメソッドを追加する既存のクラスにカテゴリがあります。

@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
4

2 に答える 2

12

あなたのコードが間違っているので、これは少し問題があります。

  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 でのみ機能することに注意してください。

于 2010-12-06T20:11:25.833 に答える
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のドキュメントはこちらです。

見つけるのに少し時間がかかりましたので、お役に立てば幸いです。

于 2011-04-14T20:52:27.337 に答える