ios objective-c storyboard automatic-ref-counting dealloc

ios - dismissViewControllerAnimated no desasigna viewcontroller



objective-c storyboard (2)

En mi caso, fue un poco más complicado. No tengo ninguna variable que tenga una referencia fuerte a mi controlador de vista, y mi controlador de vista no es un fuerte delegado a ninguna propiedad / variable contenida dentro de esta clase. Después de algunas pruebas y ensayos, descubrí que mi problema fue causado por un objeto NSTimer definido en la interfaz. El objeto del temporizador en sí mismo no es repetible, pero el método invocado por él programará el temporizador nuevamente al final, que como se puede imaginar hará referencia a este método definido en mi controlador de vista nuevamente, causando así referencias circulares. Para salir de este ciclo, tuve que invalidar el temporizador antes de descartar mi controlador de vista.

Como resumen, se trata de casos en los que un controlador de vista puede bloquearse para desasignar después de que se rechaza:

  1. El control de vista está siendo fuertemente referenciado por algún objeto externo;
  2. El controlador de vista es un delegado fuerte al que hace referencia un objeto definido dentro del controlador de vista.
  3. The dismissViewControllerAnimated: completion: block puede hacer referencia a self o tiene algún otro bloque de código que puede causar referencias circulares
  4. El controlador de vista tiene objetos NSTimer que pueden invocar algunos métodos que reprograman el temporizador

Podría haber más, pero con suerte podemos capturar muchos casos con los casos anteriores.

Primero que nada: mi proyecto está habilitado para ARC y estoy usando storyboard.

Tengo un controlador de vista que empuja un segue (modal),

[self performSegueWithIdentifier: @"goInitialSettings" sender: self];

allí estoy configurando algunos parámetros y los almacena. Cuando los parámetros están almacenados (true to a button), la aplicación debe regresar al viewcontroller original.

Esto estoy haciendo con este comando:

[self.presentingViewController dismissViewControllerAnimated:NO completion:^{}];

Me estoy dando cuenta de que el controlador de vistas que rechazo, nunca trata. ¿Cómo viene esto?

Estoy agregando el código del ''viewcontroller presentado'' a continuación:

@interface CenterChoiceController () { UIView* _titleBackground; UILabel* _lblTitle; UIButton* _btnGaVerder; UIPickerView* _myPickerView; NSArray* _centers; UILabel* _adresLine; UILabel* _cityLine; MKPointAnnotation* _point; MKMapView* _mapView; UIActivityIndicatorView* _indicator; UIAlertView* _alert; GCenter* _center; DataManager* _dm; } @end @implementation CenterChoiceController -(void)dealloc { NSLog(@"Centerchoice deallocs"); _titleBackground = nil; _lblTitle = nil; _btnGaVerder = nil; _myPickerView = nil; _point = nil; _mapView = nil; _indicator = nil; _alert = nil; _centers = nil; _adresLine = nil; _cityLine = nil; _center = nil; _dm = nil; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; _dm = [[DataManager alloc]init]; if([_dm hasConnectivity]) { [_dm fetchCentersForController:self]; } else { [self pushErrorMessage:NSLocalizedString(@"nointernetconnection", nil)]; } CAGradientLayer *bgLayer = [BackgroundLayer blueGradient]; bgLayer.frame = self.view.bounds; [self.view.layer insertSublayer:bgLayer atIndex:0]; _titleBackground = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 44)]; _titleBackground.backgroundColor = [GColor blueColor]; [self.view addSubview:_titleBackground]; _lblTitle = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width - 10, 44)]; _lblTitle.textAlignment = NSTextAlignmentRight; _lblTitle.textColor = [GColor whiteColor]; _lblTitle.text = NSLocalizedString(@"bioscoopkeuze", nil); [self.view addSubview:_lblTitle]; _btnGaVerder = [[UIButton alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 54, self.view.frame.size.width, 54)]; [_btnGaVerder setTitle:NSLocalizedString(@"gaverder", nil) forState:UIControlStateNormal]; _btnGaVerder.titleLabel.font = [_btnGaVerder.titleLabel.font fontWithSize:12]; _btnGaVerder.backgroundColor = [GColor blueColor]; [_btnGaVerder setTitleColor:[GColor whiteColor] forState:UIControlStateNormal]; [_btnGaVerder setShowsTouchWhenHighlighted:YES]; [_btnGaVerder addTarget:self action:@selector(gaVerder) forControlEvents:UIControlEventTouchUpInside]; _myPickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 44, self.view.frame.size.width, 200)]; } -(void)showLoading { NSLog(@"shows loading"); _indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; CGPoint cntr = self.view.center; _indicator.center = cntr; [_indicator startAnimating]; [self.view addSubview:_indicator]; } -(void)hideLoading { NSLog(@"hides loading"); [_indicator removeFromSuperview]; _indicator = nil; } -(void)pushData:(NSArray *)data { [self.view addSubview:_btnGaVerder]; [self.view addSubview:_myPickerView]; _centers = data; _myPickerView.delegate = self; _myPickerView.dataSource = self; _dm = [[DataManager alloc]init]; GSettings* settings = [_dm loadSettings]; if(settings == nil) { settings = [[GSettings alloc]init]; settings.chosenCenter = [_centers objectAtIndex:0]; settings.loadedCenter = [_centers objectAtIndex:0]; _center = settings.chosenCenter; settings.notificationsEnabled = YES; [self changeAddressLines]; } /*if(settings != nil) { GCenter* loaded = settings.loadedCenter; int i = 0; BOOL found = NO; while(i < [_centers count] && !found) { GCenter* center = (GCenter*)[_centers objectAtIndex:i]; if(settings.loadedCenter.iD == center.iD) { _center = center; settings.chosenCenter = center; [_dm storeSettings:settings]; found = YES; } i++; } //[self.myPickerView selectRow:i-1 inComponent:0 animated:NO]; loaded = nil; [self changeAddressLines]; } */ } -(void) pushErrorMessage: (NSString*) errorMessage { _alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"fout", nil) message:errorMessage delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil]; _alert.delegate = self; [_alert show]; } - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { if(buttonIndex == 0) { if(self.navigationController != nil) { [self.navigationController popViewControllerAnimated:YES]; } else { //[self initializeData]; } } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -(void)viewWillDisappear:(BOOL)animated { [_dm cancelCenterRequest]; /*if(self.tabBarController != nil) { dm = [[DataManager alloc]init]; settings = [dm loadSettings]; if([dm hasConnectivity]) { settings.lastUpdated = nil; [dm storeSettings:settings]; } if(settings.loadedCenter.centerCode != settings.chosenCenter.centerCode) { UIStoryboard *mystoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; SplashScreenController *controller = [mystoryboard instantiateViewControllerWithIdentifier:@"root"]; [self presentViewController:controller animated:YES completion:nil]; } dm = nil; settings = nil; } */ } -(void)gaVerder { _dm = [[DataManager alloc]init]; GSettings* settings = [_dm loadSettings]; if(settings == nil) { settings = [[GSettings alloc]init]; settings.notificationsEnabled = YES; } if(_center != nil) { settings.chosenCenter = _center; } [_dm storeSettings:settings]; [_mapView removeFromSuperview]; _mapView = nil; _titleBackground = nil; _lblTitle = nil; _btnGaVerder = nil; _myPickerView = nil; _point = nil; _indicator = nil; _alert = nil; _centers = nil; _adresLine = nil; _cityLine = nil; _center = nil; _dm = nil; [self.presentingViewController dismissViewControllerAnimated:NO completion:^{}]; //DEZE BLIJFT HELAAS IN HET GEHEUGEN HANGEN... GEEN OPLOSSING GEVONDEN //[self.navigationController popViewControllerAnimated:NO]; } //PICKERVIEWDELEGATE EN DATASOURCE // returns the number of ''columns'' to display. - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 1; } // returns the # of rows in each component.. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return [_centers count]; } - (UILabel *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { GCenter* center = (GCenter*)[_centers objectAtIndex:row]; NSString* string = center.name; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, pickerView.frame.size.width, 44)]; label.textColor = [GColor blueColor]; label.font = [label.font fontWithSize:18]; label.text = string; label.textAlignment = NSTextAlignmentCenter; return label; } - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { _center = (GCenter*)[_centers objectAtIndex:row]; [self changeAddressLines]; } -(void)changeAddressLines { if (_mapView != nil) { [_mapView removeAnnotation:_point]; } [_adresLine removeFromSuperview]; [_cityLine removeFromSuperview]; _adresLine = nil; _cityLine = nil; CGRect rctAdres = CGRectMake(0, _myPickerView.frame.origin.y + _myPickerView.frame.size.height -10, self.view.frame.size.width, 20); _adresLine = [[UILabel alloc]initWithFrame:rctAdres]; _adresLine.textAlignment = NSTextAlignmentCenter; _adresLine.textColor = [GColor greyColor]; _adresLine.text = _center.street; CGRect rctCity = CGRectMake(0, rctAdres.origin.y + rctAdres.size.height, self.view.frame.size.width, 20); _cityLine = [[UILabel alloc]initWithFrame:rctCity]; _cityLine.textAlignment = NSTextAlignmentCenter; _cityLine.textColor = [GColor greyColor]; _cityLine.font = [_cityLine.font fontWithSize:14]; _cityLine.text = _center.city; [self.view addSubview:_adresLine]; [self.view addSubview:_cityLine]; if(_mapView == nil) { double height; height = _btnGaVerder.frame.origin.y - _cityLine.frame.origin.y - _cityLine.frame.size.height; CGRect mapRect = CGRectMake(0, _cityLine.frame.origin.y+3 + _cityLine.frame.size.height, self.view.frame.size.width, height); _mapView = [[MKMapView alloc]initWithFrame:mapRect]; [self.view addSubview:_mapView]; } CLLocationCoordinate2D punt; punt.latitude = _center.latitude; punt.longitude = _center.longitude; _point = [[MKPointAnnotation alloc] init]; [_point setCoordinate:punt]; _mapView.centerCoordinate = punt; _point.title = _center.name; [_mapView addAnnotation:_point]; [_mapView setCenterCoordinate:punt animated:YES]; MKCoordinateRegion theRegion = _mapView.region; theRegion.span.longitudeDelta = 0.005; theRegion.span.latitudeDelta = 0.005; [_mapView setRegion:theRegion animated:YES]; } @end


Si su controlador de vista no se desasigna después de que se descarta, probablemente haya una fuerte referencia a ese controlador de vista en algún lugar de su código. ARC siempre desasignará objetos que ya no tienen una referencia fuerte.