UIPopovercontroller dealloc alcanzado mientras popover aún es visible

111

Les aseguro que busqué una respuesta en SO para mi pregunta, pero ninguna de ellas fue útil. Aquí tengo un código simple que debería presentar un UIImagePickerControllerdentro de un UIPopoverController:

-(void)takePicture:(id)sender{
UIImagePickerController *picker=[[UIImagePickerController alloc] init];
picker.delegate=self;
picker.sourceType=UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing=YES;
UIPopoverController *poc=[[UIPopoverController alloc] 
                            initWithContentViewController:picker];
[poc presentPopoverFromBarButtonItem:bbItem 
            permittedArrowDirections:UIPopoverArrowDirectionAny
                            animated:NO];
}

Ahora, incluso desde la primera vez que me [UIPopoveController dealloc]alcanzan mientras ... error y el programa se bloquea. No estoy reteniendo, retransmitiendo o liberando automáticamente según ARC. ¿Hay alguna consideración especial UIPopoverControllersal beneficiarse de ARC?

Mikayil Abdullayev
fuente

Respuestas:

203

UIPopoverControllers siempre debe mantenerse en una variable de instancia. Es una buena práctica crear una propiedad sólida para ello.

ACTUALIZAR:

A partir de iOS 8 deberías estar usando UIPopoverPresentationController. Entonces no necesita mantener una referencia al popover porque es administrado por el controlador de presentación.

Ejemplo de código (funciona tanto en iPhone como en iPad):

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.allowsEditing = YES;
picker.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController* popoverPC = picker.popoverPresentationController;
popoverPC.barButtonItem = bbItem;
popoverPC.permittedArrowDirections = UIPopoverArrowDirectionAny;
[self presentViewController:picker animated:YES completion:nil];
Felix
fuente
1
Oh ya veo. ¿Pero no es esto como un UIAlertView? Nunca tengo un ivar para él, solo lo asigno a init donde lo necesite, lo muestro y luego [solía] liberarlo. ¿En qué se diferencia popovercontroller?
Mikayil Abdullayev
17
@Mikayil El alertView es retenido por su supervista (como lo son todas las vistas), pero el popoverController no es una vista, por lo que no tiene una supervista, por lo que no será retenido por nadie si no lo conserva (o guárdelo en una variable fuerte que tenga un alcance que sea más largo que el método actual, por ejemplo, una iVar).
fzwo
1
Pero todavía estoy confundido sobre el recuento de retención de UIPopoverController. Porque pongo un cheque antes de asignar e iniciar uno. Y solo si es nulo, asigno uno nuevo. Pero después de asignarlo por primera vez, nunca obtengo un valor nulo. Quiero decir, llamo a un método una vez. Allí asigno e inicio mi ivar. Y la próxima vez, cuando vuelva a llamar a ese método, esta vez encuentro que mi ivar ya está asignado. Si ARC se encarga de esto, ¿cuándo lo libera? ¿O lo libera automáticamente?
Mikayil Abdullayev
@Mikayil ivars son liberados por ARC cuando el objeto es desasignado o cuando los configura como nulo
Felix
pero no han mencionado esto en la documentación, en la sección Cómo usar usan la variable local
Amit Battan
11

Cuando la función sale, no hay otra referencia al controlador popover, por lo que se desasigna demasiado pronto.

Intente agregarlo como miembro de su clase.

Tim

tarmes
fuente
¿No debería poder verlo antes de que se desasigne?
Mikayil Abdullayev
10

Agregando lo que @ phix23 respondió, cree la propiedad * poc como esta:

@property (nonatomic, retain) IBOutlet UIPopoverController *poc;

y luego cambia

UIPopoverController *poc = [[UIPopoverController alloc] 
                            initWithContentViewController:picker];

para

self.poc = [[UIPopoverController alloc] 
                            initWithContentViewController:picker];
orafaelreis
fuente
11
No tiene que ponerlo en su archivo .h. Eso lo haría público y, a menos que lo desee, simplemente conviértalo en una propiedad en su archivo .m.
Joshua Dance