我有一个显示自定义单元格的表视图,单元格包含我从文档文件夹中加载的图像。我注意到当我滚动表格时,有一些滞后,我假设是从加载磁盘中的图像。但是,图像已经加载到了这一点,所以我有点困惑。
有关优化此代码的建议,将不胜感激。我读过有关延迟加载的内容,但我不确定这是否适用于我。
我确实检查了表格是否正在重复使用这些单元格。
编辑:
- (void)configureCell:(BeerCell *)cell
atIndexPath:(NSIndexPath *)indexPath
{
Beer *beer = (Beer *) [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.displayBeerName.text = beer.name;
// check to see if there is a cached image already. Use a dictionary.
// make sure this is one of your ivars
__block UIImage *theImage = [self.imagesCache objectForKey: beer.imagePath];
// If the image is not in your cache, you need to retrieve it.
if (!theImage){
// The image doesn't exist, we need to load it from disk, web or render it
// First put a placeholder image in place. Shouldn't be any penalties after the
// first load because it is cached.
cell.beerImage.image = [UIImage imageNamed:@"beer-pic.png"];
// check to see if your image cache dictionary has been created, if not do so now
if (_imagesCache == nil) {
_imagesCache= [[NSMutableDictionary alloc] initWithCapacity:1];
}
// get a weak reference to UITableViewController subclass for use in the block
// we do this to avoid retain cycles
__weak BeerListViewController *weakSelf = self;
// do the heavy lifting on a background queue so the UI looks fast
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^ {
theImage = [UIImage imageWithContentsOfFile:beer.imagePath];
// I added this in because I create the new core data object in this class, and pass
// it to the class where I fill out the information about the beer
if (theImage) {
// Add the image to the cache
[weakSelf.imagesCache setObject:theImage forKey:beer.imagePath];
//[weakSelf.imagesCache addObject:theImage forKey:beer.imagePath];
// Check to see if the cell for the specified index path is still being used
BeerCell *theCell = (BeerCell *)[weakSelf.tableView cellForRowAtIndexPath:indexPath];
// Per the docs. An object representing a cell of the table
// or nil if the cell is not visible or indexPath is out of range.
if (theCell){
// dispatch onto the main queue because we are doing work on the UI
dispatch_async(dispatch_get_main_queue(), ^ {
theCell.beerImage.image = theImage;
[theCell setNeedsLayout];
});
}
}
});
}
else
{
// Image already exists, use it.
cell.beerImage.image = theImage;
}
}
答案 0 :(得分:1)
每当从磁盘,服务器或渲染图像中加载tableview时,您都希望将其放在后台队列中。这样做很简单,即使在3GS上也能获得很好的性能。
我使用类似的方法为tableviews生成缩略图,并从非常大的图像滚动视图,性能非常好。
试试这个:
- (void)configureCell:(CustomCell *)cell
atIndexPath:(NSIndexPath *)indexPath
{
CoreDateObject *object = (CoreDateObject *)[self.fetchedResultsController objectAtIndexPath:indexPath];
cell.displayName.text = object.name;
// check to see if there is a cached image already. Use a dictionary.
// make sure this is one of your ivars
UIImage *theImage=[self.imagesCache objectForKey: object.imagePath];
// If the image is not in your cache, you need to retrieve it.
if (!theImage){
// The image doesn't exist, we need to load it from disk, web or render it
// First put a placeholder image in place. Shouldn't be any penalties after the
// first load because it is cached.
cell.selectedImage.image=[UIImage imageNamed:@"yourPlaceHolderImage"];
// check to see if your image cache dictionary has been created, if not do so now
if (_imagesCache==nil){
_imagesCache=[NSMutableDictionary alloc] initWithCapacity:1];
}
// get a weak reference to UITableViewController subclass for use in the block
// we do this to avoid retain cycles
__weak YourTableViewControllerSubclass *weakSelf=self;
// do the heavy lifting on a background queue so the UI looks fast
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^{
theImage=[UIImage imageWithContentOfFile:object.imagePath];
// Add the image to the cache
[weakSelf.imagesCache addObject:theImage forKey:object.imagePath];
// Check to see if the cell for the specified index path is still being used
CustomCell *theCell=(CustomCell *)[weakSelf.tableView cellForRowAtIndexPath:indexPath];
// Per the docs. An object representing a cell of the table
// or nil if the cell is not visible or indexPath is out of range.
if (theCell){
// dispatch onto the main queue because we are doing work on the UI
dispatch_async(dispatch_get_main_queue(), ^{
theCell.selectedImage.image=theImage
[theCell setNeedsLayout];
});
}
}else{
// Image already exists, use it.
cell.selectedImage.image=theImage;
}
cell.rating.rate = object.rating.doubleValue;
}
答案 1 :(得分:0)
这两个链接中的一个将更好地解释这是如何正确完成的。
https://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html(官方苹果)
https://github.com/rs/SDWebImage(很好用的库)..
答案 2 :(得分:0)
cellForRowAtIndexPath:
...因此,如果在此方法中编写大量处理代码,则可以挂起滚动。因此,如果可能的话,制作一个图像数组然后使用缩略图...然后将这些图像添加到数组中的单元格。我相信你的滚动会很流畅。