Pregunta

Pregunta estúpida, pero ¿por qué necesitamos usar 'retener' al declarar una propiedad? ¿No se retiene de todos modos cuando se le asigna algo?

Mirando este ejemplo, parece que un objeto se conserva automáticamente cuando se asigna, entonces, ¿cuál es el punto?

#import "Fraction.h"
#import <stdio.h>

int main( int argc, const char *argv[] ) {
    Fraction *frac1 = [[Fraction alloc] init];
    Fraction *frac2 = [[Fraction alloc] init];

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // increment them
    [frac1 retain]; // 2
    [frac1 retain]; // 3
    [frac2 retain]; // 2

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // decrement
    [frac1 release]; // 2
    [frac2 release]; // 1

    // print current counts
    printf( "Fraction 1 retain count: %i\n", [frac1 retainCount] );
    printf( "Fraction 2 retain count: %i\n", [frac2 retainCount] );

    // release them until they dealloc themselves
    [frac1 release]; // 1
    [frac1 release]; // 0
    [frac2 release]; // 0

■ Salida

Fracción 1 Retener el recuento: 1

Fracción 2 Retener el recuento: 1

Fracción 1 Retener el recuento: 3

Fracción 2 Retener el recuento: 2

Fracción 1 Retener el recuento: 2

Fracción 2 Retener el recuento: 1

Fracción de reparto

Fracción de reparto


¡Esto me está volviendo loca!

¿Fue útil?

Solución

El comportamiento predeterminado de una propiedad es asignado, no retener. Estos no son el mismo comportamiento. Si su propiedad es para un tipo de datos primitivos, como un int, entonces asignar sería correcto. Sin embargo, si especifica (retener) y la propiedad apunta a un puntero de objeto como el objeto NSObject *, al puntero se le asigna a la dirección de memoria del objeto y su recuento de retención se incrementa por uno. Si su programa consiste en nada más que una función principal solitaria, entonces su propósito es difícil de ver. Sin embargo, suponga que su clase tenía este método:

-(void)setMyArrayWithString:(NSString *)s{
    myArray = [NSArray arrayWithObject:s];
    }

Supongamos que MyArray se define como NsArray *MyArray y tiene la declaración adecuada de @Property (retener). Todo funciona bien hasta que el método regrese. Esto se debe a que el objeto devuelto de NsArray es un objeto autorelado. Si no lo conservamos, lo lanzará NsautoreleasePool y no podremos usarlo (y obtendremos errores desagradables y malas violaciones de acceso). Para solucionar esto podemos hacer una de dos cosas:

-(void)setMyArrayWithString:(NSString *)s{
    self.myArray = [NSArray arrayWithObject:s];
// OR
    myArray = [[NSArray arrayWithObject:s] retain];    
}

La primera solución usa self.myArray para utilizar la definición @Property. Este código asigna y luego conserva el objeto para que no lo pierda cuando la función regrese. La segunda solución establece el puntero NsArray *MyArray manualmente y luego conserva manualmente el objeto NSArray. De cualquier manera, el nsautoreleasePool liberará el objeto al final de la función, sin embargo, no se deseará porque todavía tenemos nuestra retención de que lo mantenga vivo anterior.

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