【发布时间】:2011-10-14 04:18:21
【问题描述】:
我有一个系统可以从网络加载大量大图像并将它们显示在自定义表格单元格中。在较旧的设备上,内存警告发生得非常快,所以我实现了一个从表中删除一些内容的系统来尝试解决这个问题,但效果不够好(删除了很多影响 UI 的图像)。
所以我想我可以将所有图像加载到设备的缓存中,然后从那里加载它们——我已经实现了SDWebImage。这很好,但我仍然没有解决内存分配的问题,因为图像仍然一直显示并因此保存在内存中 - 导致崩溃。
我认为我需要实现一个系统,如果正在显示单元格,则显示图像(来自缓存),如果未显示单元格,则隐藏它 - 我只是坚持如何构建这样的系统。
或者这行不通?你真的可以通过从表格单元格中删除图像来保持应用程序内存较低(并阻止它出现内存警告/崩溃)吗?还是我只需要继续我之前的解决方案并删除图像/单元格,直到内存警告停止?
已更新代码
TableViewController.m
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0)
{
currentIndexPath = indexPath;
ImageTableCell *cell = (ImageTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
ImageDownloader *download = [totalDownloads objectAtIndex:[indexPath row]];
if (cell == nil)
{
cell = [[[ImageTableCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: CellIdentifier] autorelease];
}
cell.imageView.image = download.image;
return cell;
}
return nil;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int t = [totalDownloads count];
return t;
}
ImageTableCell.m - 自定义单元格
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self)
{
self.frame = CGRectMake(0.0f, 0.0f, 320.0f, 0.0f);
self.contentView.frame = CGRectMake(0.0f, 0.0f, 320.0f, 0.0f);
self.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
self.contentMode = UIViewContentModeScaleToFill;
self.autoresizesSubviews = YES;
self.contentView.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
self.contentView.contentMode = UIViewContentModeScaleToFill;
self.contentView.autoresizesSubviews = YES;
[self.imageView drawRect:CGRectMake(0.0f, 0.0f, 320.0f, 0.0f)];
self.imageView.contentMode = UIViewContentModeScaleAspectFill;
self.imageView.autoresizingMask = (UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth);
self.imageView.opaque = YES;
}
return self;
}
ImageDownloader(实现 SDWebImageManagerDelegate)
-(void) downloadImage // Comes from Model class
{
if (image == nil)
{
NSURL *url = [NSURL URLWithString:self.urlString];
SDWebImageManager *manager = [SDWebImageManager sharedManager];
// Remove in progress downloader from queue
[manager cancelForDelegate:self];
if (url)
{
[manager downloadWithURL:url delegate:self retryFailed:YES];
}
}
}
- (void)cancelCurrentImageLoad
{
[[SDWebImageManager sharedManager] cancelForDelegate:self];
}
- (void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage *)_image
{
self.image = _image;
if ([self.delegate respondsToSelector:@selector(addImageToModel:)]) [self.delegate addImageToModel:self];
}
- (void)webImageManager:(SDWebImageManager *)imageManager didFailWithError:(NSError *)error;
{
if ([self.delegate respondsToSelector:@selector(badImage)]) [self.delegate badImage];
}
【问题讨论】:
-
你能把
cellForRowAtIndexPath的方法贴出来吗? -
需要注意的是,标准单元类已经内置了一个 imageView。通过创建自己的然后将其添加到 contentView,您将失去很多 Apple 已经提供的自动优化.除非您有充分的理由使用自己的 imageView,否则请考虑放弃它并使用您已经有权访问的属性。
-
非常感谢 Greg,我已经更改为使用内置的了。
标签: ios objective-c image uitableview memory-management