¿ARC garantiza que un object se descompone instantáneamente una vez que se acaba la última reference?

En particular, este tipo de código siempre funciona según lo previsto (donde MyResourceGuard es un object que bloquea un recurso exclusivo en su método init y libera el locking en su método dealloc):

NSLog(@"About to capture some exclusive resource."); { MyResourceGuard* guard = [MyResourceGuard new]; // Do something with the exclusive resource here. } // guard is out of scope, therefore its dealloc should have // been called right away and the resource should already // be free again at this point. 

He leído en libros y blogs que a diferencia de la recolección de basura de Java, ARC destruye objects tan pronto como el conteo de references disminuye a cero (y no en algún momento de su propia conveniencia), pero no lo he leído en ningún oficial documentation de Apple. Y si eso fuera cierto, ¿por qué necesitaríamos alguna vez la nueva palabra key @autoreleasepool introducida con ARC?

Desde la debugging, siempre he visto el object desasignado de inmediato, excepto cuando se genera una exception en try-catch-block, en cuyo caso nunca se llamó a dealloc (es un error de Mac o solo uno de estos objectives aterradores C oddities?).

No. No tiene una destrucción basada en el scope determinista de los objects ObjC como muestra su ejemplo.

Por ejemplo, este progtwig podría provocar un punto muerto:

 { MyResourceGuard* guard = [MyResourceGuard new]; } { MyResourceGuard* guard = [MyResourceGuard new]; } 

Lo mejor que puede hacer si necesita esta funcionalidad es usar los types C ++ ( SBRM, RAII ), también disponible en Objective-C ++ (pero no aplicable a los objects objc).

Se acerca, pero solo tiene que esperar hasta que el recuento de reference llegue a cero para que se -dealloc a -dealloc , y es por eso que las garantías están desactivadas ( generalmente! = Siempre ). Este problema es en realidad muy similar a por qué nunca confiar o usar -retainCount (donde está disponible). Ejemplos: Autorelease Pools, excepciones, cambios en el time de ejecución o código generado por ARC, optimizaciones del comstackdor, el uso de implementaciones que tienen diferentes indicadores de generación de código podría dar como resultado que la vida del object objc se prolongue más allá del scope.

Actualizar

La página completa de ARC en el sitio de Clang es una buena lectura sobre el tema, incluidos detalles, garantías (y falta de garantías), pero en particular:

6.1. Semántica precisa de por vida

En general, ARC mantiene una invariante que un puntero object retenible mantenido en un object fuerte se retendrá durante la vida formal completa del object. Los objects sujetos a esta invariante tienen una semántica de vida precisa.

De forma pnetworkingeterminada, las variables locales de duración del almacenamiento automático no tienen una semántica de por vida precisa. Dichos objects son simplemente references sólidas que contienen valores de tipo de puntero de object retenible, y estos valores están totalmente sujetos a las optimizaciones de los valores bajo control local.

Justificación: aplicar esta semántica de vida precisa sería estrictamente prohibitivo. Muchas optimizaciones útiles que teóricamente podrían disminuir la vida útil de un object serían imposibles. Esencialmente, promete demasiado.

Una variable local de tipo de propietario de object retenible y duración de almacenamiento automático se puede anotar con el atributo objc_precise_lifetime para indicar que se debe considerar como un object con semántica de vida precisa.

Justificación: no obstante, a veces es útil poder forzar que un object se libere en un momento preciso, incluso si ese object no parece ser utilizado. Es probable que esto no sea lo suficientemente común como para que el peso sintáctico de solicitar explícitamente estas semánticas no sea gravoso, e incluso puede hacer que el código sea más claro.

Incluso si utiliza el atributo objc_precise_lifetime , se aplicará a las operaciones de recuento de references para esa fuerte variable local, no a la duración del object.

este tipo de código siempre funcionará. (o al less mientras ARC funcione como lo hace en este momento) Un pequeño ejemplo para el ciclo de vida del object en ARC:

 { NSString *a = [[NSString alloc] init]; //object allocation a = nil; // object is deallocated as it was created in this scope NSString *b = [NSString string]; //method call which returns an object (always autoreleased) b = nil; // object is not deallocated as it was not created in this scope and is therefore autorelased }