Pregunta

Tengo una categoría en una clase existente que añade una propiedad y unos métodos a la clase.

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

@property (nonatomic, retain) NSString *aProperty;

@end

En el archivo de implementación, quiero liberar esta propiedad cuando se cancela la asignación del objeto. Sin embargo, si declaro dealloc en esta clase, se anulará el dealloc de la clase original de lo que entiendo. ¿Cuál es entonces la forma correcta de lanzar este aProperty cuando se cancela la asignación del objeto?

@implementation AClass (ACategory)

@synthesize aProperty;

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

@end
¿Fue útil?

Solución

Bueno, esto es un poco problemático, ya que su código es incorrecto.

  1. No se puede declarar variables de instancia en una categoría; utilizando la última Objective-C ABI, puede declarar nuevas variables de instancia dentro de una extensión de clase (@interface AClass () {//...), pero que es diferente de una categoría (@interface AClass (ACategory)).
  2. Incluso si pudiera, la sintaxis para la declaración de variable de instancia es que estar encerradas entre llaves después de la línea @interface.

Se puede declarar una propiedad en una categoría, pero que tendrá que definir su almacenamiento sin necesidad de utilizar una nueva variable de instancia (por lo tanto, en lugar de @dynamic @synthesize).


En cuanto a su pregunta real, no se puede llamar a la aplicación original de un método reemplazado a menos que utilice el método Swizzling-(facilitado por las funciones de tiempo de ejecución como method_exchangeImplementations). Recomiendo en contra de hacer esto de todos modos; que es realmente aterrador y peligroso.


Actualización: Explicación de variables de instancia en Extensiones de clase

Una extensión de clase es como una categoría, pero es anónimo y debe ser colocado dentro del archivo .m asociado con la clase original. Parece que:

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

Su aplicación debe estar en el bloque @implementation principal de su clase. Así:

@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

Por lo tanto, una extensión de clase es útil para mantener las variables de instancia privadas y los métodos de la interfaz pública, pero no le ayudará a agregar variables de instancia de una clase sobre la cual no tienen control. No hay ningún problema con anulando -dealloc, ya que acaba de ponerlo en práctica, como lo haría normalmente, mientras incluyendo cualquier gestión de memoria necesaria para las variables de instancia que se establezcan, en la extensión de clase.

Tenga en cuenta que esto sólo funciona con la última de 64 bits de Objective-C ABI.

Otros consejos

Como acotación al margen, puede utilizar referencias asociadas a " simular la adición de variables de instancia de objeto a una clase existente ".

En esencia, se puede añadir un objeto asociado de la siguiente manera:

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

Y liberar el objeto asociado mediante el envío de las negativas:

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

La documentación de Apple es aquí .

Me tomó un tiempo para encontrar, así que espero que ayude a alguien.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top