Cómo transferir la propiedad de un @autoreleasepool con ARC

Tengo el siguiente código

- (NSString *)stringByEscapingXMLEntities; { NSString *result; @autoreleasepool { result = [self stringByReplacingOccurrencesOfString:@"&" withString:@"&"]; result = [result stringByReplacingOccurrencesOfString:@"\"" withString:@"""]; // ... lot of -stringByReplacingOccurrencesOfString: calls result = [result stringByReplacingOccurrencesOfString:@" " withString:@" "]; } return result; } 

Ahora me pregunto cómo transferiría el result propiedad del método. Antes de ARC, habría conservado el result antes de salir del bloque de autorelease y lo devolví autoelevado al final del método.

¡Gracias!

Hay dos forms de hacerlo:

  • Cambie el nombre del método a algo así como copyStringByEscapingXMLEntities : la copy indica la transferencia de propiedad y ARC crea el código en consecuencia.
  • Anexe, en el encabezado, NS_RETURNS_RETAINED a la definición de método como esta: - (NSString *)stringByEscapingXMLEntities NS_RETURNS_RETAINED .

EDIT: Como se mencionó 'iljawascoding', el @autoreleasepool no tiene ninguna necesidad real de mantenerse, excepto para la optimization.


EDIT 2: Y restring: ARC siempre hace lo correcto . Todas las cosas que intentaste (tu comentario) resultan en el mismo progtwig correcto, aunque con la falta de alguna optimization si el resultado se definió como __strong .

Deshágase de la autorelease por completo. Según Apple, ARC insertá automáticamente la versión necesaria después de que su código se haya completado con las instancias temporales almacenadas en 'resultado'. No hay nada que ganar al crear tu propio grupo de autorelease aquí.

El código que ha publicado es correcto. Cualquier locking tiene una causa diferente.

Debido a que el result es una reference sólida fuera del scope de autorelease, ARC es responsable de mantenerlo vivo al salir del grupo, y lo hace. No necesitas hacer nada especial.

Más específicamente, ARC genera un código equivalente a esto:

 void *_arp = objc_autoreleasePoolPush(); temp1 = objc_retainAutoreleasedReturnValue([self stringByReplacingOccurrencesOfString:@"&" withString:@"&"]); temp2 = objc_retainAutoreleasedReturnValue([temp1 stringByReplacingOccurrencesOfString:@"\"" withString:@"""]); objc_release(temp1); result = objc_retainAutoreleasedReturnValue([temp2 stringByReplacingOccurrencesOfString:@" " withString:@" "]); objc_release(temp2); // result is not released here objc_autoreleasePoolPop(_arp); return objc_autoreleaseReturnValue(result); // Result is returned autoreleased, or handed off to a matching objc_retainAutoreleasedReturnValue() in the caller. 

Tenga en count que las variables temporales se manejan con objc_retainAutoreleasedReturnValue / objc_release pairs. Debido a la optimization de time de ejecución implementada por objc_retainAutoreleasedReturnValue y objc_retainAutoreleasedReturnValue , esto significa que los valores temporales realmente se liberarán inmediatamente sin que nunca se pongan en una agrupación -stringByReplacingOccurrencesOfString: si -stringByReplacingOccurrencesOfString: está construido con ARC. Mi conjetura sería que la mayoría de los frameworks del sistema aún no son, sin embargo.

¿Por qué no usar [[NSString alloc] initWithString:result] antes de que se @autoreleasepool scope @autoreleasepool ? ¿Pero por qué el ARP en primer lugar?