¿Por qué este código resulta en EXC_BAD_ACCESS cuando se usa ARC?

Estoy convirtiendo un viejo proyecto de iPhone para usar ARC. Presento un controller de vista modal y obtengo EXC_BAD_ACCESS al descartarlo, no puedo entender por qué, y sospecho que me falta algo fundamental sobre cómo funciona ARC.

El controller de vista que se presenta es CorrectionsController, y utiliza un delegado para permitir que su controller de vista presentador lo ignore. Estos son los bits relevantes del file de encabezado:

@protocol CorrectionsControllerDelegate - dismissCorrectionsController; @end @property (nonatomic, weak) id<CorrectionsControllerDelegate> correctionsDelegate; 

El controller se inicializa en este método:

 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil delegate:(id<CorrectionsControllerDelegate>)_delegate { if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { self.correctionsDelegate = _delegate; // do other init stuff } return self; } 

El button de rechazo llama a este método:

 - (void)cancelCorrection { if (self.correctionsDelegate) [self.correctionsDelegate dismissCorrectionsController]; // EXC_BAD_ACCESS happens here } 

El controller de vista de presentación inicializa el controller de correcciones de esta manera:

 // in .h file @property (nonatomic, strong) CorrectionsController *corrections; @property (nonatomic, strong) UINavigationController *secondNavigationController; // in .m file NSString *nibName = @"CorrectionsController"; self.corrections = [[CorrectionsController alloc] initWithNibName:nibName bundle:nil delegate:self]; self.secondNavigationController = [[UINavigationController alloc] initWithRootViewController:self.corrections]; if (isiPad()) { self.secondNavigationController.modalPresentationStyle = UIModalPresentationFormSheet; } [self presentViewController:self.secondNavigationController animated:YES completion:nil]; 

Y implementa el protocolo CorrectionsControllerDelegate:

 - (void)dismissCorrectionsController { [self dismissViewControllerAnimated:TRUE completion:nil]; } 

Ahora, la parte divertida. Al pasar por el código, la ejecución fluye a cancelCorrection, ingresa dismissCorrectionsController en el delegado, vuelve a cancelCorrection y EXC_BAD_ACCESS al final de cancelCorrection.

introduzca la descripción de la imagen aquí

introduzca la descripción de la imagen aquí

self.correctionsDelegate parece estar apuntando a un object válido en todo momento (inspeccionarlo en la vista Variables muestra el object y los valores que esperaba, y consigo lo siguiente en la console que parece estar bien).

 (lldb) po self.correctionsDelegate <SyncController: 0x17b9a970> 

Las partes que realmente me confunden:

1) el rastreo de stack muestra que EXC_BAD_ACCESS está sucediendo dentro de objc_retain . ¿Por qué? ¿Qué se retiene aquí?

2) ¿a qué se refiere la dirección de la memory 0x44?

La mejor explicación que puedo encontrar hasta ahora es que el controller modal (CorrectionsController) parece liberarse de inmediato en dismissCorrectionsController y ya no es válido cuando la ejecución vuelve a cancelCorrection. Este cambio parece solucionar el crash:

 - (void)cancelCorrection { [self.correctionsDelegate performSelector:@selector(dismissCorrectionsController) ]; } 

Marcaré esta respuesta como aceptada pero todavía no tiene sentido para mí, así que si alguien tiene una mejor explicación de lo que está sucediendo, estaré encantado de aceptar esa respuesta.

Creo que esta respuesta es muy tarde para ayudar a preguntar alex_c pero podría ayudar a alguien.

El código tiene un problema.

 @protocol CorrectionsControllerDelegate - dismissCorrectionsController; @end 

tipo de retorno perdido

 @protocol CorrectionsControllerDelegate - (void)dismissCorrectionsController; @end