Cuando se desasigna a sí mismo al descartar el controller de vista

Tengo una pregunta sobre desasignación de memory y lockings / cierres.

Lo que sigue es el método Swift

self!.dismissViewControllerAnimated(false, completion: { println(self); }) 

O el método objective C

  [self dismissViewControllerAnimated:NO completion:^{ NSLog("%@",self); }]; 

Realmente agradecería que alguien pudiera explicar cuándo se desasignaría en el método anterior. ¿Es después de que se ejecuta el bloque de finalización o antes? Entiendo que ARC lo ha cuidado, pero me gustaría saber si el post se libera en el bloque de finalización o después de eso. Por lo tanto, si hago alguna limpieza menor en el bloque de finalización (acceso a mí mismo), ¿es seguro / aceptable o no?

Realmente hay dos preguntas separadas para comprender la respuesta por completo:

1. ¿Cuándo se publican las variables referencedas dentro de los cierres?

Puedes pensar en un cierre como cualquier otro tipo (en Swift realmente lo son). Cada cierre crea una fuerte propiedad sobre las variables a las que se hace reference dentro de él, incluido el self . Esto garantiza que nunca haga reference a una variable que ha sido desasignada. Al igual que en cualquier otro object, cuando el cierre se desasigna, libera su propiedad sobre todas sus variables.

Si el cierre es lo único con una fuerte reference a esa variable, la variable se desasignará cuando se desaloje el cierre.

Entonces, en resumen, las variables permanecen en la memory siempre y cuando el cierre esté todavía en la memory.

2. ¿Cuándo se arreglan los acuerdos?

Ahora, la segunda parte de esto que es importante comprender, es cuándo se elimina el cierre de un cierre. Puede almacenar un cierre en una variable:

 func myMethod() { var myClosure = { println(self) } myClosure() } 

En este caso, el cierre tiene una fuerte reference de su variable myClosure y el cierre tiene una fuerte reference a self . Tan pronto como myClosure salga del scope, es decir, cuando myMethod salga, será desasignado. Cuando eso sucede, se liberará.

También puede tener una situación, como en su pregunta, en la que está pasando un cierre a otro método. En este caso, el método en el que está pasando el cierre está capturando una fuerte reference a su cierre. Cuando salga ese método, liberará su cierre, el cierre será desasignado, y liberará todas las variables capturadas en él.

La exception

A veces es necesario definir un cierre que no se adueñe de una variable. Haría esto para evitar references circulares . Puede leer más en la documentation de Apple sobre qué es una reference circular y cómo evitarlos aquí . Sin embargo, es importante darse count de que a less que haga un esfuerzo explícito (y código), los cierres siempre capturarán references fuertes a las variables referencedas dentro de él.

En Swift, al desarrollar / depurar y tratar de comprender el momento de las operaciones, puede agregar lo siguiente a sus controlleres de vista (o cualquier class), para rastrear si la instancia está a punto de desasignarse o cuándo.

Aunque eso no ayudará a detectar 'fuertes ciclos de reference' que se describen aquí:

https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html

 deinit { println(__FUNCTION__, "\(self)") }