10

Estoy trabajando en una aplicación de collage de fotos iPad que atrae tal vez cientos de UIImageView s en la pantalla a la vez.Obligar a un objeto a desasignar bajo ARC

Hay un botón que permite al usuario "volver a crear", que se supone que debe ejecutar un for en [photo removeFromSuperview] en todas las fotos y luego inicializar un nuevo lote, en ese orden.

Estoy usando ARC, y mi consola me dice que el método deno se está llamando hasta DESPUÉS de que se haya dibujado el siguiente lote, lo que significa que estoy teniendo problemas de memoria, aunque estoy tratando de eliminar el primer conjunto antes de agregar el siguiente conjunto.

¿Hay alguna manera de 1) esperar hasta que todas las fotos se hayan tramitado correctamente o 2) forzar todas las fotos a tratarloc inmediatamente bajo ARC?

+1

Radu tiene razón en que una vez que elimine las vistas de las imágenes y quite todas las referencias sólidas a ellas, se desasignarán inmediatamente. No es como el viejo problema de MRC donde el uso descuidado de 'autorelease' podría resultar en un aplazamiento de la liberación de la memoria hasta el final del ciclo de ejecución actual. Si sigues teniendo problemas, probablemente necesites mostrarnos un fragmento de código sobre cómo crear, agregar y guardar referencias a las imágenes y sus vistas de imágenes. Pero si elimino la vista de imagen y creo una nueva, el trato para la anterior sucede antes de que llegue la creación de la nueva. – Rob

Respuesta

13

Probablemente esté poniendo sus vistas de imagen en un grupo de liberación automática sin darse cuenta. Es posible que pueda solucionar esto al incluir su propio grupo de autorreleases en su ciclo for-loop.

Por ejemplo, hice un proyecto de prueba muy simple con una vista de imagen y un botón debajo de mi vista de nivel superior. Cuando toco el botón, elimina la vista de la imagen y crea una nueva. Elimina la vista de la imagen al recorrer las subvistas de la vista de nivel superior. Aquí está el código:

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    [self initImageView]; 
} 

- (IBAction)redoWasTapped:(id)sender { 
    [self destroyImageView]; 
    [self initImageView]; 
} 

- (void)destroyImageView { 
    for (UIView *subview in self.view.subviews) { 
     if ([subview isKindOfClass:[UIImageView class]]) { 
      [subview removeFromSuperview]; 
     } 
    } 
} 

- (void)initImageView { 
    UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"picture.jpg"]]; 
    imageView.frame = CGRectInset(self.view.bounds, 100, 100); 
    [self.view addSubview:imageView]; 
} 

@end 

Cuando me encontré con esto bajo el instrumento Asignaciones con “los recuentos de referencia Record” habilitadas, vi que cada vista de la imagen eliminada no se cancela la asignación durante destroyImageView. En cambio, fue desasignado más tarde cuando el ciclo de ejecución llamó al -[NSAutoreleasePool release].

Entonces cambió destroyImageView para gestionar su propia piscina autorelease:

- (void)destroyImageView { 
    @autoreleasepool { 
     for (UIView *subview in self.view.subviews) { 
      if ([subview isKindOfClass:[UIImageView class]]) { 
       [subview removeFromSuperview]; 
      } 
     } 
    } 
} 

Cuando me encontré de nuevo en virtud de instrumentos, vi que cada vista de la imagen eliminada se cancela la asignación durante destroyImageView, al final del bloque de @autoreleasepool.

+0

Para entenderlo, lea sobre [ NSAutoreleasePool y Run Loops] (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html) – DanSkeel

9

ARC dealloc s cualquier objeto para el que no hay más referencias fuertes. Entonces, para dealloc algo, simplemente configure todas las variables que lo señalan como nil y asegúrese de que el objeto no esté involucrado en ninguna referencia circular.

+3

¿Se tramita inmediatamente después de que no haya más referencias, o simplemente se tramita en algún momento posterior? Empíricamente, parece suceder de inmediato, pero ¿hay alguna garantía de eso? Y si no, entonces establecer en cero no obliga a un dealloc. – prewett

+0

Para entenderlo, lea sobre [NSAutoreleasePool y Run Loops] (https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html) – DanSkeel

Cuestiones relacionadas