UITableView 和 UINavigationController 中的内存管理
Posted
技术标签:
【中文标题】UITableView 和 UINavigationController 中的内存管理【英文标题】:Memory management in UITableView and UINavigationController 【发布时间】:2012-02-06 04:35:40 【问题描述】:更新
我已经更新了代码,我发现我可以 nil iconDownLoader 或 downloadArray 但不能同时使用它们。
我认为 unload 中的 nil 与 dealloc 中的 release 不同?而 self.xxx = nil 是必要的吗?我已经更新了代码。它工作正常(虽然它没有释放所有内存)但我不太明白。
你能解释一下为什么吗?谢谢
我搜索了很多,但仍然无法解决这个内存管理问题。希望有人可以帮助我解决它并理解其原理。
我有一个 UIViewController,里面有一个 UITableView。表格视图加载自定义单元格和图像。它每次都会消耗大量内存,并且在我 popViewControllerAnimated 后不会释放内存。多次push和popviewController后内存会增加到200m。
这是一些代码,任何帮助将不胜感激。
- (void)didReceiveMemoryWarning
[super didReceiveMemoryWarning];
#pragma mark - View lifecycle
- (void)viewDidUnload
self.newsArray = nil;
self.newsTableView = nil;
self.indicatorView = nil;
// self.iconDownLoader = nil;
self.downloadArray = nil;
[super viewDidUnload];
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"NewsCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
[[NSBundle mainBundle] loadNibNamed:@"NewsTableViewCell" owner:self options:nil];
cell = self.newsTableViewCell;
self.newsTableViewCell = nil;
// read from newsModel
NewsModel *news = [newsArray objectAtIndex:indexPath.row];
UILabel *label;
label = (UILabel *)[cell viewWithTag:10];
label.text = [NSString stringWithString:news.title];
label = nil;
label = (UILabel *)[cell viewWithTag:11];
label.text = [NSString stringWithString:news.description];
UIImageView *imageView = (UIImageView *)[cell viewWithTag:12];
imageView.image = news.image;
if (news.image == nil)
imageView.image = [UIImage imageNamed:IconPlaceHolder];
IconDownLoader *iconDownLoader = [[IconDownLoader alloc] init];
iconDownLoader.url = news.imageUrl;
iconDownLoader.delegate = self;
iconDownLoader.indexPath = indexPath;
if (appDelegate.ip4 == YES)
iconDownLoader.width = 300;
iconDownLoader.height = 150;
else
iconDownLoader.width = 150;
iconDownLoader.height = 75;
[downloadArray addObject:iconDownLoader];
[iconDownLoader start];
return cell;
#pragma mark - IconDownLoaderDelegate
- (void)iconDownLoadFinsh:(NSData *)imageData row:(NSIndexPath *)indexPath
UITableViewCell *cell = [newsTableView cellForRowAtIndexPath:indexPath];
UIImageView *imageView = (UIImageView *)[cell viewWithTag:12];
if (imageData != 0)
imageView.image = [UIImage imageWithData:imageData];
else
imageView.image = [UIImage imageNamed:@"icon57"];
NewsModel *newsModel = [newsArray objectAtIndex:indexPath.row];
newsModel.image = [UIImage imageWithData:imageData];
这是 IconDownloader
#import "IconDownLoader.h"
#import "ASIHTTPRequest.h"
@implementation IconDownLoader
@synthesize delegate = _delegate;
@synthesize url = _url;
@synthesize indexPath = _indexPath;
@synthesize width = _width;
@synthesize height = _height;
@synthesize request = _request;
- (void)start
NSString *originalString = @"width=%s&height=%s";
NSString *newString = [NSString stringWithFormat:@"width=%d&height=%d&type=jpg", self.width, self.height];
NSString *resizedURL = [self.url stringByReplacingOccurrencesOfString:originalString withString:newString];
NSURL *url = [NSURL URLWithString:[resizedURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
_request = [ASIHTTPRequest requestWithURL:url];
if (_indexPath)
_request.userInfo = [NSDictionary dictionaryWithObject:_indexPath forKey:@"indexPath"];
[_request setDelegate:self];
[_request startAsynchronous];
- (void)requestFinished:(ASIHTTPRequest *)request
NSInteger statusCode = request.responseStatusCode;
switch (statusCode)
case 401: // Not Authorized: either you need to provide authentication credentials, or the credentials provided aren't valid.
break;
case 200:
NSData *responseData = [request responseData];
if (!responseData)
UIAlertView *alertView;
alertView = [[UIAlertView alloc] initWithTitle:@"Oops" message:[NSString stringWithFormat:@"Download failed in row %d", _indexPath.row] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
return;
[_delegate iconDownLoadFinsh:responseData row:[request.userInfo objectForKey:@"indexPath"]];
break;
case 304: // Not Modified: there was no new data to return.
break;
case 400: // Bad Request: your request is invalid, and we'll return an error message that tells you why. This is the status code returned if you've exceeded the rate limit
break;
case 403: // Forbidden: we understand your request, but are refusing to fulfill it. An accompanying error message should explain why.
break;
case 404: // Not Found: either you're requesting an invalid URI or the resource in question doesn't exist (ex: no such user).
UIAlertView *alertView;
alertView = [[UIAlertView alloc] initWithTitle:@"Oops" message:@"Classical 404, please contact with your administer" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
break;
case 500: // Internal Server Error: we did something wrong. Please post to the group about it and the Weibo team will investigate.
case 502: // Bad Gateway: returned if Weibo is down or being upgraded.
case 503: // Service Unavailable: the Weibo servers are up, but are overloaded with requests. Try again later.
UIAlertView *alertView;
alertView = [[UIAlertView alloc] initWithTitle:@"Oops" message:@"503 error, service unavailable" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
default:
- (void)dealloc
if (_request != nil)
[_request clearDelegatesAndCancel];
@end
【问题讨论】:
你没有释放IconDownLoader
。
你说的太对了,答对了,你就能得到我的十美分:)
【参考方案1】:
你没有释放IconDownLoader
。
【讨论】:
一个简单的问题,如果我没有 iconDownLoader,那么在 downloadArray 中是什么,因为在 downloadArray 中有很多 iconDownloader。 ([downloadArray addObject:iconDownLoader];) 我应该按顺序将它们归零吗? 如果我同时做这些,就会有一个 exc_bad_access。 self.iconDownLoader = nil; self.downloadArray = nil; @ThinkChris:等等,你在用 ARC 吗? rm -rf:是的,为什么要问?刚试过,如果我删除 self.downloadArray = nil; 就没有 exc_bad_access。 downloadArray 是在 initWithNibName 中创建的。 @ThinkChris:那我的回答实际上是无效的。 ARC应该会为你发布。关于您的第一个问题,如果您稍后访问downloadArray
(顺便说一下,您应该使用self.downloadArray
设置它)那么您不不想取消它。以上是关于UITableView 和 UINavigationController 中的内存管理的主要内容,如果未能解决你的问题,请参考以下文章
删除大标题 UINavigationBar 中 UISearchController 顶部的 1px 行
在 UISplitViewController 中弹出 UINavigationController 会导致奇怪的过渡
UITableView backgroundColor 和 UITableView.appearance
UIView 与 UITableview 和 UIImageview,使用 reloadData 访问 UITableview