0

我有一个显示自定义单元格的表格视图,这些单元格包含我从文档文件夹加载的图像。我注意到,当我滚动表格时,会有一些滞后,我假设这是从磁盘加载图像。但是,图像已经加载,所以我有点困惑。

有关优化此代码的建议,将不胜感激。我已阅读有关延迟加载的信息,但我不确定这是否适用于我。

我确实检查过以确保表格正在重用单元格。

编辑:

- (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;
    }
}
4

3 回答 3

1

每当您从磁盘、服务器加载或为 tableview 渲染图像时,您都希望将其放在后台队列中。这样做很简单,即使在 3GS 上也能获得出色的性能。

我使用类似的方法从非常大的图像中生成表格视图和滚动视图的缩略图,并且性能非常好。

试试这个:

- (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;
}
于 2012-07-06T23:34:00.357 回答
0

这两个链接之一将更好地解释这是如何正确完成的..

https://developer.apple.com/library/ios/#samplecode/LazyTableImages/Introduction/Intro.html(苹果官方)

https://github.com/rs/SDWebImage (使用不错的库)..

于 2012-07-05T15:41:04.387 回答
0

cellForRowAtIndexPath:每次滚动表格视图时都会调用...因此,如果您在此方法中编写大型处理代码,它可能会挂起您的滚动。因此,如果可能的话,为此制作一个图像数组,然后使用缩略图图像......然后将这些图像添加到数组中的单元格中。我相信你的滚动会很流畅。

于 2012-07-05T15:45:21.227 回答