【问题标题】:Custom Table Cell Scrolling自定义表格单元格滚动
【发布时间】:2012-07-05 15:19:11
【问题描述】:

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

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

我确实检查了表格以确保重复使用单元格。

编辑:

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

【问题讨论】:

    标签: iphone objective-c ios


    【解决方案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;
    }
    

    【讨论】:

    • 我喜欢这个解决方案,但我遇到了一个问题。当我在应用程序启动时第一次加载表格时,我得到的只是一个占位符图像,直到我滚动表格,然后出现正确的图像,任何想法或建议。我用我使用的代码编辑了我的答案。
    • 如果您找到对您的解决方案有帮助的教程,我们将不胜感激提供链接
    • 如果您在应用程序加载时获得了一个占位符,并且表格单元格仅在您滚动时更新,那么您做错了什么,或者您没有调整代码以适应您的具体情况。就教程而言,请查看苹果的 wwdc 2011 关于使用 gcd 的视频。
    • 谢谢!这是正确的,我在调整图像大小时遇到​​问题,我的编码无法正常工作,导致加载完整图像。这就是性能不佳的原因。
    【解决方案2】:

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

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

    https://github.com/rs/SDWebImage(很好用的库)..

    【讨论】:

    • 我查看了延迟加载,但我没有从网络获取图像,只是从磁盘读取
    • 这就是最初设计它的原因.. 但它所做的是将图像加载过程放在不同的线程上。这将加快加载速度并使滚动更加流畅。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多