Intereting Posts
Силовой портрет в одном регуляторе зрения делает изначально другое портретное Изменяет ли непрозрачность ADBannerView правильное функционирование? iOS Simulator показывает либо пустой черный, либо белый экран NSURLConnection не возвращает данные Как отображать несколько выносок MKPointAnnotation сразу в MKMapView? Пожар события для анимации основной анимации после завершения анимации uiviewimage (монофонический) как получить автоматический макет для работы в Xcode не может запустить мое приложение cordova в новом ios8 Как внедрить Google Login для приложения iOS? Найти и заменить регулярное выражение NSString Для iOS, Safari, VoiceOver, как мне заставить VoiceOver читать пользовательские переключатели? Межплатформенная виртуальная валюта iOS При нажатии на сообщение не открывается страница приложения в AppStore Слияние двух изображений в быстром Установка backgroundColor не работает на UIView

dealloc vs ViewDidDissapear для управления памятью

У меня есть несколько представлений, которые анализируют xml, загруженные из Интернета.

Инструмент утечки инструментов говорит мне, что у меня есть утечки, когда я освобождаю данные в методе dealloc, но не тогда, когда я помещаю [objectname release]; имени [objectname release]; внутри viewDidDissapear .

Это кардинальный грех?

Исходя из фона ac / c ++, я обнаруживаю, что управление памятью obj-c очень сбивает с толку!

EDIT: Вот код:

 #import "SuggestedFriendList.h" @implementation SuggestedFriendList @synthesize maincell,nationalityimageview, subjectimageview, accommodationimageview; - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName attributes:(NSDictionary *)attributeDict { currentElement = [[elementName copy] autorelease]; if ([elementName isEqualToString:@"shared"]) { tshared = [[NSMutableString alloc] init]; } if ([elementName isEqualToString:@"fullname"]) { tfullname = [[NSMutableString alloc] init]; } if ([elementName isEqualToString:@"nationality"]) { tnationality = [[NSMutableString alloc] init]; } if ([elementName isEqualToString:@"subject"]) { tsubject = [[NSMutableString alloc] init]; } if ([elementName isEqualToString:@"accommodation"]) { taccommodation = [[NSMutableString alloc] init]; } if ([elementName isEqualToString:@"memberid"]) { tmemberid = [[NSMutableString alloc] init]; } if ([elementName isEqualToString:@"count"]) { tcount = [[NSMutableString alloc] init]; } } - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { if ([currentElement isEqualToString:@"shared"]) { [tshared appendString:string]; } if ([currentElement isEqualToString:@"fullname"]) { [tfullname appendString:string]; } if ([currentElement isEqualToString:@"nationality"]) { [tnationality appendString:string]; } if ([currentElement isEqualToString:@"subject"]) { [tsubject appendString:string]; } if ([currentElement isEqualToString:@"accommodation"]) { [taccommodation appendString:string]; } if ([currentElement isEqualToString:@"memberid"]) { [tmemberid appendString:string]; } if ([currentElement isEqualToString:@"count"]) { [tcount appendString:string]; } } - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if ([elementName isEqualToString:@"shared"]) { [lshared addObject:tshared]; [tshared release]; } if ([elementName isEqualToString:@"fullname"]) { [lfullname addObject:tfullname]; [tfullname release]; } if ([elementName isEqualToString:@"nationality"]) { [tnationality appendString:@".png"]; [lnationality addObject:tnationality]; [tnationality release]; } if ([elementName isEqualToString:@"subject"]) { [lsubject addObject:tsubject]; [tsubject release]; } if ([elementName isEqualToString:@"accommodation"]) { [laccommodation addObject:taccommodation]; [taccommodation release]; } if ([elementName isEqualToString:@"memberid"]) { [lmemberid addObject:tmemberid]; [tmemberid release]; } if ([elementName isEqualToString:@"count"]) { count = [[NSMutableString alloc] init]; count = tcount; [tcount release]; } } -(void)fetchsuggestions { MyManager *sharedManager = [MyManager sharedManager]; suggestiondetailxml = [[NSMutableData alloc] init]; NSString *urlString = [NSString stringWithFormat:@"http://secreturl.com/a.php?username=%@&password=%@",sharedManager.user,sharedManager.passw]; NSURL *url = [NSURL URLWithString:urlString]; NSURLRequest *req = [NSURLRequest requestWithURL:url]; connection = [[NSURLConnection alloc] initWithRequest:req delegate:self startImmediately:YES]; } -(void) connection:(NSURLConnection *)conn didReceiveData:(NSData *)data { [suggestiondetailxml appendData:data]; } -(void) connectionDidFinishLoading:(NSURLConnection *)conn { NSString *xmlcheck = [[[NSString alloc] initWithData:suggestiondetailxml encoding:NSUTF8StringEncoding] autorelease]; NSLog(@"%@",xmlcheck); lshared = [[NSMutableArray alloc] init]; lfullname = [[NSMutableArray alloc] init]; lnationality = [[NSMutableArray alloc] init]; lsubject = [[NSMutableArray alloc] init]; laccommodation = [[NSMutableArray alloc] init]; lmemberid = [[NSMutableArray alloc] init]; NSXMLParser *parser = [[NSXMLParser alloc] initWithData: suggestiondetailxml]; [parser setDelegate:self]; [parser parse]; [parser release]; //[xmlcheck release]; //causes crash [connection release]; connection = nil; [suggestiondetailxml release]; [[self tableView] reloadData]; NSLog(@"%@",lmemberid); } - (id)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self) { // Custom initialization } return self; } - (void)didReceiveMemoryWarning { // Releases the view if it doesn't have a superview. [super didReceiveMemoryWarning]; // Release any cached data, images, etc that aren't in use. } #pragma mark - View lifecycle - (void)viewDidLoad { [super viewDidLoad]; [[self navigationItem] setTitle:@"My Culture"]; // Uncomment the following line to preserve selection between presentations. // self.clearsSelectionOnViewWillAppear = NO; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem; } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // eg self.myOutlet = nil; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self fetchsuggestions]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [lshared release]; [lfullname release]; [lnationality release]; [lsubject release]; [laccommodation release]; [lmemberid release]; //[count release]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Return the number of sections. return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [lfullname count]; } -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 93.0; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil]; if (cell==nil) { [[NSBundle mainBundle] loadNibNamed:@"SuggestedFriendCell" owner:self options:nil]; cell = maincell; //self.detailcell = nil; } UILabel *name; name = (UILabel *)[cell viewWithTag:4]; name.text=[lfullname objectAtIndex:indexPath.row]; if(([[lshared objectAtIndex:indexPath.row]isEqualToString:@"all"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"nationalityandaccommodation"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"nationalityandsubject"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"nationality"])) { UIImageView *nationality; nationality = (UIImageView *)[cell viewWithTag:1]; nationality.image=[UIImage imageNamed:[lnationality objectAtIndex:indexPath.row]]; } if(([[lshared objectAtIndex:indexPath.row]isEqualToString:@"all"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"nationalityandaccommodation"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"subjectandaccommodation"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"accommodation"])) { UIImageView *accommodation; accommodation = (UIImageView *)[cell viewWithTag:2]; accommodation.image=[UIImage imageNamed:@"accommodation.jpeg"]; } if(([[lshared objectAtIndex:indexPath.row]isEqualToString:@"all"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"nationalityandsubject"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"subjectandaccommodation"])||([[lshared objectAtIndex:indexPath.row]isEqualToString:@"subject"])) { UIImageView *subject; subject = (UIImageView *)[cell viewWithTag:3]; subject.image=[UIImage imageNamed:@"degree.jpg"]; } return cell; } #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Navigation logic may go here. Create and push another view controller. /* <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil]; // ... // Pass the selected object to the new view controller. [self.navigationController pushViewController:detailViewController animated:YES]; [detailViewController release]; */ MyManager *sharedManager = [MyManager sharedManager]; int row = indexPath.row; sharedManager.interrogatedmemberid=[lmemberid objectAtIndex:row]; ViewFriendProfile *frienddetail_vc = [[[ViewFriendProfile alloc] init] autorelease]; [[self navigationController] pushViewController:frienddetail_vc animated:YES]; } -(void)dealloc { [super dealloc]; } @end 

Когда я раскомментирую [выпуск tcount], он вызывает сбои: почему это.

PS: Я очень сожалею о форматировании: как вы можете копировать и вставлять код, чтобы он отображался в блоках кода?

благодаря

Чтобы понять, что происходит, вам нужно понять, как работают viewWillAppear и viewWillDisappear.

Оба метода вызывается несколько раз в жизненном цикле контроллера просмотра, в зависимости от того, нажали ли вы / постулируете диспетчер представлений или если вы показываете / отклоняете модаль от контроллера вида.

Например:

  1. Push viewController A: viewDidLoad и viewWillAppear, вызываемые в viewController A
  2. Нажмите viewController B из viewController A: viewWillDisappear вызывается на viewController A, viewDidLoad и viewWillAppear, вызываемые в viewController B
  3. Pop viewController B, чтобы вернуться к viewController A: viewWillDisappear вызван в viewController B, viewDidUnload, вызванный в viewController B, dealloc, вызванный в viewController B, viewWillAppear, вызванный viewController A
  4. Отобразить модальный вид из viewController A: viewWillDisappear вызывает viewController A
  5. Отклонить модальный: viewWillAppear, вызванный viewController A
  6. Pop viewController A: viewWillDisappear вызывает viewController A, viewDidUnload, вызываемый в viewController A, dealloc, вызываемый в viewController A

Похоже, что вы выделяете объект в viewWillAppear, который вызывается несколько раз, но освобождая его в методе dealloc, который вызывается только один раз, следовательно, утечка памяти .

Освобождение объекта в viewWillDisappear – это балансировка выделенных в viewWillAppear, следовательно, утечки нет.

Все, что я могу сказать в этот момент, если у вас нет веских оснований выделять что-то в viewWillAppear (т. Е. Вы знаете, что делаете), не делайте этого.

Там не так много, что я могу вам сказать … публикация большего количества кода для того, что вы пытаетесь сделать, может помочь вам получить более сложный ответ 🙂

Надеюсь, это помогло.


EDIT после того, как код был опубликован.

Прежде всего, вы имеете в виду «когда я раскомментирую [ count release]»? Не могли бы вы отправить сообщение консоли для этого сбоя? Это сбой, потому что parserDidEndElement – это место, где он выделен, но он освобождается в viewWillDisappear. Если они не сбалансированы, вы получите EXC_BAD_ACCESS

Переход к вашей памяти. Теперь я вижу, почему освобождение в представленииWillDisappear устраняет утечки. Вы вызываете fetchsuggestions на viewWillAppear, который, в свою очередь, создает и отключает запрос URL. Это приведет к connectionDidFinishLoading при успешном соединении. Здесь вы размещаете различные ивары. Поскольку я упоминал ранее, что viewWillAppear вызывается несколько раз, это означает, что вы несколько раз отключаете соединение, что приводит к тому, что connectionDidFinishLoading вызывается несколько раз.

Вот почему освобождение в viewWillDisappear исправляет утечки, потому что для каждого выделения на viewWillAppear вы балансируете его, освобождая в viewWillDisappear .

Однако вы пропустили, что ваша программа выйдет из строя, когда нет сети. Это связано с тем, что connectionDidFinishLoading не будет вызван, когда нет сети. Теперь, когда вы попытаетесь освободиться в viewWillDisappear , вы получите EXC_BAD_ACCESS, поскольку вы пытаетесь освободить ранее освобожденные экземпляры, которые больше никогда не были выделены в viewWillAppear .

Я не думаю, что мне нужно много раз называть fetchsuggestions на viewWillAppear, если вы не намеренно делаете это.

Это самая яркая вещь, которую я вижу прямо сейчас … проблемы могут быть (и, вероятно, есть) несколько, но как насчет того, чтобы начать с реструктурирования кода, имея в виду, что несколько несбалансированных распределений и выпусков внутри viewWillAppear / Disappear могут не быть хорошая идея…? 🙂

Как-то странно выпускать что-либо в viewWillDisappear, но если вы выделите его в viewWillAppear, это правильная вещь. Я думаю, вы должны выделять свои объекты в viewDidLoad и освобождать их в viewDidUnload. В некоторых случаях это могло бы избежать ненужного их воссоздания.

Вы также должны выпустить сохраненные ivars в dealloc. Просто убедитесь, что, когда вы отпустите их в других методах, вы установите их на нуль, поэтому, если они снова будут выпущены, это просто отправка релиза в нуль, что не работает.

Одним из инструментов, который я нахожу полезным в поиске потенциальных утечек памяти, является сборка> Анализ в Xcode.

Он сообщает вам, какая строка была выделена, и где она может протекать позже по коду. Он также сообщает вам, где вы сделали неправильный счет уменьшения количества [объекта].

Возможно, вы не полностью освобождаете представление, и dealloc никогда не вызывается.