iOS 5:UITableView单元格不能平滑滚动

时间:2012-06-28 17:53:42

标签: iphone ios uitableview

使用:

  • iOS 5,ARC,StoryBoards。

每个单元格上都有1个图像和文本。滚动时图像不会调整大小。有两个版本的图像image.png和image@2x.png。

通过在故事板中使用UIImageView和UILabel来管理自定义单元格。

代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
Continent *continent=[self.items objectAtIndex:[indexPath row]];
ContinentCell *cell = (ContinentCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell.continentName.text=continent.continentName;
    cell.textView.text=continent.countriesHash;
    cell.imageView.image=[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:continent.continentImage ofType:@"png"]];
 return cell;
}

邪恶在哪里?提前谢谢。

4 个答案:

答案 0 :(得分:12)

[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:continent.continentImage ofType:@"png"]];

很贵。您希望在后台异步加载图像,然后在准备好时将其显示在主线程上。

这是一个非常粗略的解决方案

    cell.imageView.image = nil;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
      UIImage * img = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:continent.continentImage ofType:@"png"]];
      dispatch_sync(dispatch_get_main_queue(), ^{
        cell.imageView.image = img;
      });
    });

答案 1 :(得分:5)

26:48 中查看Polishing your App: Tips and Tricks to Improve Responsiveness and Performance video of WWDC 2011。他们已经准确地讨论了你所面临的问题。不要错过,这会非常有帮助..!

答案 2 :(得分:2)

确保您的图片不大,然后:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"Cell";
    Continent *continent=[self.items objectAtIndex:[indexPath row]];
    ContinentCell *cell = (ContinentCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if(cell == nil) cell = [[ContinentCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]
    cell.continentName.text = continent.continentName;
    cell.textView.text = continent.countriesHash;
    cell.imageView.image = [UIImage imageNamed:continent.continentImage];
    return cell;
}

我做了两个重大改变:

  1. 添加if(cell == nil) [[ContinentCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier],因为我没有找到初始化单元格的代码(除非你使用-registerNib或其他超级sectet函数,我不能说因为它在NDA)

  2. 用简单的imageWithContentsOfFile:...替换了imageNamed,因为您从主捆绑中加载了图片,如果图片不大,-imageNamed会缓存它,因此加载速度更快。 (和-imageNamed不需要文件扩展名)

答案 3 :(得分:2)

- (UITableViewCell *)tableView:(UITableView *)tableView 
                                 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    Continent *continent=[self.items objectAtIndex:[indexPath row]];
    ContinentCell *cell = (ContinentCell*)[tableView 
                               dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[ContinentCell alloc] 
                               initWithStyle:UITableViewCellStyleDefault 
                               reuseIdentifier:CellIdentifier];
     }
    cell.continentName.text=continent.continentName;
    cell.textView.text=continent.countriesHash;
    //cell.imageView.image=[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] 
                        pathForResource:continent.continentImage ofType:@"png"]];
    cell.imageView.image = [UIImage cachedImage:continent.continentImage];
    return cell;
}

我建议你使用imageNamed而不是imageWithContentsOfFile。

imageNamed 方法在缓存中加载图片,下次从高速缓存加载图像时,imageWithContentsOfFile方法从指定路径加载图像而不加NO cahching,它将在内存中创建多个副本。

您可以创建自己的图像缓存方法。只需声明NSMutableDictionary * imagedCacheDict

如果内存不足,可以通过删除所有对象 [imagedCacheDict removeAllObjects]

 - (UIImage*)cachedImage:(NSString*)fileName
{
   UIImage *cacheImage = [imagedCacheDict objectForKey:fileName];

   if (nil == cacheImage)
   {
      NSString *cacheImageFile = [NSString stringWithFormat:@"%@.png", 
                                   [[NSBundle mainBundle] resourcePath], fileName];
      cacheImage = [UIImage imageWithContentsOfFile:cacheImageFile];
      [imagedCacheDict setObject:cacheImage forKey:fileName];
   }
   return cacheImage;
}

所以,永远不要使用imageNamed方法,它会耗费大量内存来带出你的应用程序。