gpt4 book ai didi

iphone - TableView 滚动异步

转载 作者:可可西里 更新时间:2023-11-01 03:38:49 24 4
gpt4 key购买 nike

我正在将图像加载到表格 View 单元格,每个单元格都有一个图像。我已经将几个教程改编成下面的代码,但我的速度仍然很慢。

我正在从文档目录加载这些图像。有关如何加快此过程的任何提示或想法?

编辑修改后的代码:

Beer *beer = (Beer *) [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.displayBeerName.text = beer.name;

// did we already cache a copy of the image?
if (beer.image != nil) {
// good. use it. this will run quick and this will run most of the time
cell.beerImage.image = beer.image;
} else {
// it must be the first time we've scrolled by this beer. do the expensive
// image init off the main thread

cell.beerImage.image = nil; // set a default value here. nil is good enough for now

[self loadImageForBeer:beer atIndexPath:indexPath];
}
- (void)loadImageForBeer:(Beer *)beer atIndexPath:(NSIndexPath *)indexPath {

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{

UIImage *image = [UIImage imageWithContentsOfFile:beer.imagePath];
beer.image = image;

dispatch_sync(dispatch_get_main_queue(), ^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.beerImage.image = image;
});
});
}

最佳答案

您的算法看起来不错。您已经避免了许多典型的陷阱。如果您仍然遇到 UI 性能问题,我建议您采取以下措施:

  1. 您应该尝试将图像缓存在内存中。您可以使用 NSMutableArrayNSMutableDictionary,但在 Best way to cache images on ios app? Caleb 讨论了 NSCache 类的优点,它简化了过程。如果您缓存图像,请确保您响应内存压力并在必要时清除缓存。您可以响应 didReceiveMemoryWarning 或将自己添加为通知中心的 UIApplicationDidReceiveMemoryWarningNotification 的观察者。

  2. 确保您的缓存图像是缩略图大小的,否则您的 UI 中总是会有一点卡顿(如果您需要调整大小的算法,请告诉我们)并且它会不必要地占用内存;

  3. 当您将图像更新分派(dispatch)回主队列时,您应该异步执行(为什么后台队列会在等待 block 被发送回主队列时挂起并占用资源完成...一旦您在快速滚动期间备份了几张图像,这尤其是一个问题);和

  4. 当您分派(dispatch)回主队列时,您应该检查以确保从 cellForRowAtIndexPath 获得的单元格不是 nil(因为如果单元格加载逻辑得到备份过多(尤其是在速度较慢的设备上),理论上您可能会将有问题的单元格滚出屏幕,您的算法可能会崩溃。

我使用的算法与您的非常相似,具有几乎相同的 GCD 结构(带有上述注意事项)并且滚动非常流畅,即使在较旧的设备上也是如此。如果你想让我发布代码,我很乐意。

如果您仍然遇到问题,CPU 分析器非常适合识别瓶颈并让您知道应该将注意力集中在何处。网上有一些很棒的 WWDC session ,重点介绍如何使用 Instruments 来识别性能瓶颈,我发现它们对熟练使用 Instruments 非常有帮助。

这是我的代码。在 viewDidLoad 中,我初始化我的图像缓存:

- (void)initializeCache
{
self.imageCache = [[NSCache alloc] init];
self.imageCache.name = @"Custom Image Cache";
self.imageCache.countLimit = 50;
}

然后我在我的 tableView:cellForRowAtIndexPath 中使用它:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ilvcCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

// set the various cell properties

// now update the cell image

NSString *imagename = [self imageFilename:indexPath]; // the name of the image being retrieved

UIImage *image = [self.imageCache objectForKey:imagename];

if (image)
{
// if we have an cachedImage sitting in memory already, then use it

cell.imageView.image = image;
}
else
{
cell.imageView.image = [UIView imageNamed:@"blank_image.png"];

// the get the image in the background

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

// get the UIImage

UIImage *image = [self getImage:imagename];

// if we found it, then update UI

if (image)
{
dispatch_async(dispatch_get_main_queue(), ^{

// if the cell is visible, then set the image

UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell)
cell.imageView.image = image;

[self.imageCache setObject:image forKey:imagename];
});
}
});
}

return cell;
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];

[self.imageCache removeAllObjects];
}

顺便说一句,您可能会考虑进一步优化,将缓存的图像预加载到单独的队列中,而不是在单独的线程中即时加载图像。我认为没有必要,因为这对我来说似乎已经足够快了,但它是加速 UI 的另一种选择。

关于iphone - TableView 滚动异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11486828/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com