2012-03-10 23 views
6

¿Cuál es el equivalente a [[something retain] autorelease] en ARC?¿Cuál es el equivalente a '[[retener algo] autorelease]' en ARC?

Tengo un problema donde una clase DBRequest llama a mi delegado para indicar que se ha completado. Mi delegado luego establece la instancia de DBRequest en nil, que es la de dealloc. Pero luego, cuando la pila sale de mi delegado y salta de vuelta a DBRequest, por supuesto, se cuelga.

Si no estuviera en ARC, en mi delegado simplemente haría [[theDbRequest retain] autorelease] antes de liberar mi referencia, de modo que sobreviva el tiempo suficiente hasta que el siguiente ciclo de ejecución lo libere automáticamente.

¿Qué debería hacer en ARC?

Respuesta

6

Cómo sobre la adición de algo así como

__strong DBRequest * myself = self; 
[delegate reportDone]; 

creo que va a incrementar el objeto mismo hasta el final de la función de impedir que mueran al inicio.

+0

Yo * podría * abrir el código de Dropbox y hacer eso ... esperaba que hubiera una manera de hacerlo. sin necesidad de modificar su código. – Chris

+3

@Chris, Ok, no me di cuenta de que ese bit estaba en su código. No estoy seguro, pero es posible que pueda colocar una 'DUDequesting' '__autoreleasing' theDBRequest = dbRequest' en su código. –

+1

Al final, eso es exactamente lo que hice :) – Chris

3

Mi delegado luego establece la instancia de DBRequest en nil, que es la de dealloc. Pero luego, cuando la pila sale de mi delegado y salta de vuelta a DBRequest, por supuesto, se cuelga.

Seguramente esta fue siempre una mala estrategia, y su [[theDbRequest retain] autorelease] siempre cubría el problema, ¿no?

Simplemente no hacer nada. Entonces tu variable de instancia se queda; ¿Y qué? Usted sabe que ARC lo liberará cuando lo desasiguen.

Lo importante es no liberar theDbRequest, pero para establecer la referencia de theDbRequest a que (delegado) a cero, por lo que no trata de devolver la llamada cuando ya no existe. Su propio dealloc sería un buen lugar para hacerlo.

Espero que entienda el problema correctamente. Si no, ¡publica un código!

+0

Creo que es un El problema causado por la API de Dropbox en cuestión no está escrito usando ARC, por lo que Arc de alguna manera no puede determinar la propiedad en cuestión. Sé que cada vez que llamas a un delegado que probablemente se liberará, es una buena idea llamar a "auto retener automáticamente", pero la API de Dropbox no está haciendo eso, así que tengo que hacer algo. ¿Pero que? – Chris

+0

Aquí hay algo interesante también, si no configuro el DbRequest en cero, nunca se libera en absoluto (incluso después de que se libera mi delegado). ARC funciona de manera misteriosa? Tentado a volver corriendo a tierra no arqueada ... – Chris

+0

Lo siento, no conozco la API de DropBox. ¿Podría haber un problema de nombres? ARC hace suposiciones sobre cómo administrar la memoria según el * nombre * del método cuando pasamos de un archivo que no es ARC a un archivo ARC. Hay un muy buen video de WWDC 2011 que trata sobre eso; hay formas de evitarlo agregando un calificador que le dice a ARC qué hacer. – matt

3

Como @ Matt dice si simplemente no hace nada ARC debe limpiar cuando se cancela la asignación de su objeto - la asignación de la DBRequest se crea a una variable de instancia que se encarga (proporcionan por supuesto, su objeto dura más que el objeto que está creando).

Si necesita cancelar la asignación del DBRequest antes de su objeto muere, entonces necesita un "truco" compatible con ARC equivalente a [[theDbRequest retain] autorelease]. Ahora, a menos que esté construyendo sus propios grupos de autorizaciones automáticas, su enfoque anterior se activaría al final del evento actual. Siguiendo esa lógica intento:

  1. añadir un método para su clase que simplemente establece theDbRequest a nil, vamos a llamar a esta cleanUpTheDbRequest.
  2. Cambiar la devolución de llamada delegado para invocar [self performSelectorOnMainThread:@selector(cleanUpTheDbRequest) withObject:nil waitUntilDone:NO] en lugar de asignar directamente a niltheDbRequest

Esto debe retrasar la asignación de nil hasta después del final del evento actual, al igual que su autorelease "truco" lo hizo.También funciona si su DBRequest vive en varios eventos: el método anterior se activa al finalizar el evento en el que se llama al autorelease, este método al final del evento se llama al método delegado.

Cuestiones relacionadas