自定义表格单元滚动

时间:2012-07-05 15:19:12

标签: iphone objective-c ios

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

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

我确实检查了表格是否正在重复使用这些单元格。

编辑:

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

3 个答案:

答案 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: ...因此,如果在此方法中编写大量处理代码,则可以挂起滚动。因此,如果可能的话,制作一个图像数组然后使用缩略图...然后将这些图像添加到数组中的单元格。我相信你的滚动会很流畅。

相关问题