2012-02-03 8 views
12

Como asumí, esto debería funcionar bien para objeto inmutable bajo ARC:Objective-C objeto inmutable copyWithZone: compatible con ARC realización

- (id) copyWithZone:(NSZone *)zone { 
    return self; 
} 

Pero si necesito copia profunda, yo debería escribir algo como esto:

- (id) copyWithZone:(NSZone *)zone { 
    Immutable *copy = [[Immutable alloc] initWithStr:str]; 
    return copy; 
} 

Entonces, si asumí que es correcto, ARC entendería la situación (1) y (2) y tomaría la decisión correcta sobre "+1" para las referencias.

¿Estoy en lo cierto?

+0

Creo que ARC básicamente trata a todos los objetos que regresan y se liberan automáticamente con la excepción de 'alloc ~' y 'copy ~'. Trato todos los objetos que regresan bajo ARC son '' retenidos '' y '' guardados '' semánticamente. Y solo agrega uno más -retain' para alloc y copy cases. Como resultado, se pueden eliminar una retención y una liberación automática, y solo se conservará una retención ... – Eonil

Respuesta

12

Parece que tengo razón: no encuentro ninguna documentación concreta sobre el tema, pero creo un proyecto de prueba separado con ARC desactivado, luego elijo migrar a ARC. Aquí es código sin ARC:

- (id) copyWithZone:(NSZone *)zone { 
    return [self retain]; 
} 

Esto es lo que tengo después de la migración:

- (id) copyWithZone:(NSZone *)zone { 
    return self; 
} 

Es una magia cómo ARC trabaja a veces, pero parece que deberíamos creer que va haciendo su trabajo bien. :-)

+1

Una copia debe devolver un objeto diferente (un puntero diferente). Entonces su solución puede causar problemas ... – Macmade

+8

@Macmade si el objeto es inmutable, es aceptable devolver un puntero retenido al mismo objeto. NSString, NSDate, etc. todos hacen esto. –

+0

Claro, es aceptable. Pero es importante ser consciente de esto, especialmente si se trata de la comparación de punteros para algunas tareas. :) – Macmade

4

El recuento automático de referencias, as stated in the specification, obedece las prácticas de nomenclatura de Cacao estándar. Esto significa que se supone que los métodos con los prefijos init, copy y new devuelven los objetos que posee la persona que llama (recuento de referencias +1). Por lo tanto, si devuelve un objeto de uno de esos métodos, ARC lo maneja automáticamente de esta manera ya que no puede retenerlo explícitamente.

El único caso problemático al respecto que Apple ha señalado sería un marco de terceros que utiliza el código de referencia manual contado en el que los autores no siguieron las convenciones de nomenclatura estándar. Un ejemplo que dieron fue un método que devolvía una cadena autorretratada llamada copyRightString. Esto será sobreexplotado en ARC, ya que asumirá que un objeto contado de referencia +1 es devuelto por dicho método.

Puede fuerza del arco para tratar este método de manera especial usando un modificador como el siguiente:

-(NSString*) copyRightString NS_RETURNS_NON_RETAINED; 

Mugunth Kumar tiene un poco más de detalle sobre esto en his ARC migration writeup.

+0

Es '+ alloc',' + copy', y '+ new'. '-init' no cambia el recuento de retención del objeto. –

+0

@JonathanGrynspan - Correcto, pero parecen buscar el prefijo '-init'. De la especificación vinculada anteriormente: "El escenario más común de este modelo es el retorno retenido de los métodos init, alloc, new y copy, pero hay otros casos en los frameworks."Esto es probable en combinación con' -alloc', pero he desconectado el analizador estático en el pasado con algo que he prefijado accidentalmente con '-init' por sí mismo. –

+0

' -init' devuelve un objeto que debe ser liberado porque solo se llama inmediatamente después de '+ alloc'. La retención real es (en papel) hecha en' + alloc', '-init' solo" adelante ". –

Cuestiones relacionadas