ios automatic-ref-counting nsoperation ios8 nsautoreleasepool

¿Se requiere @autoreleasepool para el uso moderno de iOS 8 NSOperation?



automatic-ref-counting ios8 (1)

He leído la Guía de Programación de Concurrencia

En la guía, el texto indica que las colas de envío de GCD definen sus propios grupos de @autoreleasepool y menciona que aún se recomienda definir uno a nivel de envío, pero para NSOperation no se dice nada y el código de ejemplo proporcionado por Apple tampoco muestra el uso de La estructura de @autoreleasepool. El único lugar donde @autoreleasepool se menciona vagamente en el contexto de NSOperation es en el Historial de revisiones,

2012-07-17 - Se eliminó información obsoleta sobre el uso del grupo de autorelease con las operaciones.

Mirando el código de muestra disponible en línea, por ej. http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues está haciendo uso de @autoreleasepool en las implementaciones de objetos basados ​​en NSOperations, por ejemplo:

@implementation ImageDownloader - (void)main { @autoreleasepool { ... } } @end

  1. ¿Cómo debo implementar los objetos modernos de NSOperation?
  2. ¿A qué se refería la actualización de Apple del 2012-07-17?

Si está derivando de NSOperation e implementando el método main , no necesita configurar un grupo de autorelease. La implementación predeterminada del método de start NSAutoReleasePool un NSAutoReleasePool , llama a main y luego NSAutoReleasePool el NSAutoReleasePool . Lo mismo ocurre con NSInvocationOperation y NSBlockOperation , que comparten la misma implementación del método de start .

El siguiente es un desmontaje abreviado del método de start para NSOperation . Tenga en cuenta las llamadas a NSPushAutoreleasePool, luego una llamada a main seguida de una llamada a NSPopAutoreleasePool:

Foundation`-[newMyObj__NSOperationInternal _start:]: 0x7fff8e5df30f: pushq %rbp ... 0x7fff8e5df49c: callq *-0x16b95bb2(%rip) ; (void *)0x00007fff8d9d30c0: objc_msgSend 0x7fff8e5df4a2: movl $0x1, %edi ; new NSAutoreleasePool is pushed here 0x7fff8e5df4a7: callq 0x7fff8e5df6d6 ; NSPushAutoreleasePool ... NSOperation main is called 0x7fff8e5df6a4: callq *-0x16b95dba(%rip) ; (void *)0x00007fff8d9d30c0: objc_msgSend 0x7fff8e5df6aa: movq %r15, %rdi ; new NSAutoreleasePool is popped here, which releases any objects added in the main method 0x7fff8e5df6ad: callq 0x7fff8e5e1408 ; NSPopAutoreleasePool

Aquí hay una instantánea de un código de ejemplo ejecutándose

  1. MyObj está asignado en el método main y me aseguro de que el objeto debe ser liberado automáticamente.
  2. main regresa a _start , y la siguiente imagen muestra un seguimiento de pila con MyObj dealloc que llama el grupo de autorelease actual, que aparece dentro de _start

Para referencia, este es el código de ejemplo que usé para verificar el comportamiento:

#import <Foundation/Foundation.h> @interface MyObj : NSObject @end @implementation MyObj - (void)dealloc { NSLog(@"dealloc"); } @end @interface TestOp : NSOperation { MyObj *obj; } @end @implementation TestOp - (MyObj *)setMyObj:(MyObj *)o { MyObj *old = obj; obj = o; return old; } - (void)main { MyObj *old = [self setMyObj:[MyObj new]]; [self setMyObj:old]; } @end int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!"); NSOperationQueue *q = [NSOperationQueue new]; TestOp *op = [TestOp new]; [q addOperation:op]; [op waitUntilFinished]; } return 0; }

Grand Central Dispatch gestiona de manera similar los grupos de autorelease para las colas de envío, según la Guía de programación de concurrencia :

Si su bloque crea más de unos pocos objetos Objective-C, es posible que desee encerrar partes del código de su bloque en un bloque @autorelease para manejar la administración de la memoria de esos objetos. Aunque las colas de despacho de GCD tienen sus propios grupos de autorelease, no ofrecen ninguna garantía sobre cuándo se drenan esos grupos. Si su aplicación tiene memoria limitada, la creación de su propio grupo de autorelease le permite liberar la memoria para los objetos lanzados automáticamente a intervalos más regulares.