14

No estoy del todo claro sobre los patrones de propiedad del objeto requeridos para las siguientes instancias. Cuando mi UIViewController presenta un controlador de popover, una hoja de acción u otro controlador de vista como modal, ¿debo suspender una referencia retenida a ese controlador hijo hasta que se haya descartado?Conservar/liberar patrón para UIPopoverController, UIActionSheet y controladores de vista modal?

En otras palabras, ¿las siguientes líneas de código efectivamente "transfieren" la propiedad, o no?

[aPopoverController presentPopoverFromBarButtonItem:someButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO]; 

[anActionSheet showFromBarButtonItem:someButtonItem animated:NO]; 

[aViewController presentModalViewController:someOtherViewController animated:YES]; 

¿Alguien me puede indicar documentación explícita sobre este tema?

Respuesta

26

UIPopoverViewController tiene una gestión/posesión de memoria ligeramente diferente. Presentar un popover no retiene la memoria, por lo que no puede transferir la propiedad de su popviewcontroller al objeto de presentación.

Para evitar la pérdida de memoria, tiene que adoptar el UIPopoverControllerDelegate y poner en práctica el método DidDismissPopOver de la siguiente manera:

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController { 
    [popoverController release]; 
} 

De esta manera, se puede alloc seguro y presentar un Popover:

-(void)showSearch:(id)sender { 
    SearchViewController *searchVC = [[SearchViewController alloc] init]; 
    UIPopoverController *popVC = [[UIPopoverController alloc] initWithContentViewController:searchVC]; 
    popVC.delegate = self; 
    [popVC setPopoverContentSize:CGSizeMake(320, 100)]; 
    [popVC presentPopoverFromRect:CGRectMake(200, 200, 320, 100) inView:self.view permittedArrowDirections:0 animated:YES]; 
    [searchVC release]; 
} 
+1

Cuidado, searchVC está goteando si lo haces de esta manera. Agregue una liberación automática. – steipete

+0

Sí, se filtró searchVC. En lugar de una liberación automática, una simple versión también funcionará. Agregue esto a la última línea: '[searchVC release];' –

+1

Como documentación para 'popoverControllerDidDismissPopover:' dice: _ "El controlador popover no llama a este método en respuesta a llamadas programáticas al método dismissPopoverAnimated: Si descarte el popover mediante programación, debe realizar cualquier acción de limpieza inmediatamente después de llamar al método dismissPopoverAnimated: "_. Así que si utiliza 'dismissPopoverAnimated:' también deberá llamar a la versión posterior, de lo contrario, obtendrá una filtración. – ivanzoid

1

La presentación de un controlador de vista modal conserva el UIViewController. Esto no está claro en los documentos. Sin embargo, he comprobado usando el siguiente código ...

NSLog(@"BEFORE %d", [self.setupViewController retainCount]); 
[self.navigationController presentModalViewController:self.setupViewController animated:YES]; 
NSLog(@"AFTER %d", [self.setupViewController retainCount]); 

El self.setupViewController ya se retiene localmente, pero la presentación que muestre lo siguiente:

2010-05-19 10:07:36.687 LocateMe[27716:207] BEFORE 1 
2010-05-19 10:07:36.762 LocateMe[27716:207] AFTER 3 

por lo que probablemente está siendo retenido en el propiedad modalViewController local, así como también en la jerarquía de vistas. Descartarlo equilibrará estos.

Por lo tanto, la línea de fondo es, consérvela si desea controlarla directamente, pero no es necesario.

EDITAR - Para que quede claro, el patrón correcto es conservar siempre un objeto si se establece como su delegado. Eso es porque deberías configurar al delegado para que sea cero en tu dealloc por seguridad. Sin embargo, en la práctica, siempre se descartará un controlador modal antes de realizar el desglose, por lo que no es un problema. Notarás que Apple también rompe esta regla en [UIView setAnimationDelegate:], que en realidad conserva el delegado que configuraste.

+0

lo haría también agregue que gran parte del código de muestra de Apple inicializa un UIViewController, lo presenta modalmente y luego lo libera. Mira el ejemplo AddMusic. – DougW

+0

¿Lo mismo ocurre con los popovers y las hojas de acción? –

+0

Sí, puede disparar UIAlertView y luego lanzarlo. O puede conservarlo si quiere hacer algo al respecto. De cualquier manera está bien, solo asegúrate de equilibrar tus retenciones/lanzamientos. – DougW

Cuestiones relacionadas