Intereting Posts
Изображение UIPastboard не может быть вставлено в Notes.app ios8 iPad иногда резиновые ленты с -webkit-overflow-scrolling: touch почему изменение режима содержимого UIImageView влияет на его автоматическую компоновку в Xcode6? Ошибка компоновщика Apple Mach-O Предупреждение о Xcode 5.1 Процесс XCode / IOS по-прежнему работает на iPhone после убийства TwitterKit: общий экземпляр твиттера, не сохраняющий аутентифицированную сессию Нет ли варианта раскадровки в XCode 5.1.1? ios изменяет цвет элемента навигатора при наличии комплекта событий Возможно ли переопределить назначенный инициализатор с помощью инициализатора удобства? iOS: читатель ZBarCode не работает с пользовательским кликом UISegmentedControl Meteor mobile-config.js accessRule не работает Игра в пейзаже, но вид в портрете? Почему пиктограммы SimplePing от Apple преуспевают на iphone в AIRPLANE MODE? Пользовательский класс и видение UISearchBar Как получить список друзей из Facebook iOS sdk

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: Я очень сожалею о форматировании: как вы можете копировать и вставлять код, чтобы он отображался в блоках кода?

благодаря

Solutions Collecting From Web of "dealloc vs ViewDidDissapear для управления памятью"

Чтобы понять, что происходит, вам нужно понять, как работают 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 никогда не вызывается.