Objective-C освобождает собственность, объявленную в категории? - PullRequest
6 голосов
/ 06 декабря 2010

У меня есть категория в существующем классе, которая добавляет свойство и несколько методов к классу.

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

12 голосов
/ 06 декабря 2010

Ну, это немного проблематично, поскольку ваш код неверен.

  1. Вы не можете объявить переменные экземпляра в категории;используя последний Objective C ABI, вы можете объявить новые переменные экземпляра в расширении класса (@interface AClass () {//...), но это отличается от категории (@interface AClass (ACategory)).
  2. Даже если вы могли бы, синтаксисНапример, объявление переменной заключается в том, что они заключены в фигурные скобки после строки @interface.

Вы можете объявить свойство в категории, но вам придется определить его хранилище без использования новогопеременная экземпляра (следовательно, @dynamic вместо @synthesize).


Что касается вашего фактического вопроса, вы не можете вызвать исходную реализацию переопределенного метода, если не используете метод swizzling (облегченный)по времени выполнения функций, таких как 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-битным ABI Objective-C.

5 голосов
/ 15 апреля 2011

Кроме того, вы можете использовать связанные ссылки до ", имитирующие добавление переменных экземпляра объекта к существующему классу ".

По сути, вы можете добавитьсвязанный объект, как показано ниже:

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: здесь .

Мне понадобилось время, чтобы найти, поэтому я надеюсь, что это кому-нибудь поможет.

...