简体   繁体   English

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

[英]iOS 5: UITableView cells are not scrolling smooth

Using: 使用:

  • iOS 5, ARC, StoryBoards. iOS 5,ARC,StoryBoards。

Have 1 image and text on every cell. 每个单元格上都有1个图像和文本。 Images are not getting resized while scrolling. 滚动时图像不会调整大小。 Have two versions of images image.png and image@2x.png. 有两个版本的images image.png和image@2x.png。

The custom cell was managed by drugging UIImageView and UILabel in storyboard. 通过在故事板中使用UIImageView和UILabel来管理自定义单元格。

Code: 码:

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

Where's the evil? 邪恶在哪里? Thank you in advance. 先感谢您。

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

Is expensive. 价格昂贵。 You want to load the image the image asynchronously in the background then present it on the main thread when ready. 您希望在后台异步加载图像,然后在准备好时将其显示在主线程上。

Here's a very rough solution 这是一个非常粗略的解决方案

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

Check out Polishing your App: Tips and Tricks to Improve Responsiveness and Performance video of WWDC 2011 from 26:48 . 查看抛光您的应用程序:提示和技巧,以提高响应度和性能视频的WWDC 201126:48 They have discussed exactly about the problem you are facing. 他们已经准确地讨论了你所面临的问题。 Don't miss out, it would be really helpful..! 不要错过,这将是非常有帮助的..!

Make sure that your images are not big and then: 确保您的图片不大,然后:

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

I made 2 significant changes: 我做了两个重大改变:

  1. Added if(cell == nil) [[ContinentCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] , because I didn't find the code for initializing cell (unless you use -registerNib or the other super-sectet function, which I can't say because it's under NDA) 新增if(cell == nil) [[ContinentCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]因为我没有找到初始化细胞(除非你使用的代码-registerNib或其他超sectet功能,我可以”说因为它在NDA下

  2. Replaced imageWithContentsOfFile:... with simple imageNamed , because you load the image from your main bundle and, if image is not big, -imageNamed caches it, so it loads quicker. 替换了imageWithContentsOfFile:...使用简单的imageNamed ,因为你从主包加载图像,如果图像不大, -imageNamed缓存它,所以加载速度更快。 (and -imageNamed doesn't need the file extension) (和-imageNamed不需要文件扩展名)

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

I will recommend you to use imageNamed instead of imageWithContentsOfFile. 我建议你使用imageNamed而不是imageWithContentsOfFile。

imageNamed method loads the image in cache and next time it will load from cache, where as imageWithContentsOfFile method loads the image from your specified path without NO cahching and it will create multiple copy in memory. imageNamed方法将图像加载到缓存中 ,下次它将从缓存加载,其中imageWithContentsOfFile方法从指定的路径加载图像而没有NO cahching,它将在内存中创建多个副本。

You can create your own image cache method. 您可以创建自己的图像缓存方法。 Just declare NSMutableDictionary *imagedCacheDict 只需声明NSMutableDictionary * imagedCacheDict

If you run out of memory you can remove all the objects by [imagedCacheDict removeAllObjects] 如果内存不足,可以通过 [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;
}

So, never use the imageNamed method, it will bring out your application by consuming lot of memory. 因此,永远不要使用imageNamed方法,它会通过消耗大量内存来显示您的应用程序。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM