UICollectionView在加载单元格时滚动不流畅。

36

我的应用程序中有一个画廊,使用UICollectionView。 单元格大约为70,70大小。 我在画廊中使用来自列表中的ALAssetLibraryALAssets

我正在使用通常的模式填充单元格:

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{

  mycell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
  mycell.imageView.image = [[UIImage imageWithCGImage:[alassetList objectAtIndex:indexpath.row] thumbnail]];
  return mycell;
}

我的画廊滚动不流畅。我不知道为什么会这样。我尝试添加NSCache来缓存缩略图像(认为创建图像可能很耗费资源),但这并没有提高性能。

我希望UI像原生应用程序一样顺畅。

现在我怀疑可能是UICollectionViewCell prepareForReuse中的某些内容阻塞了dequeueReusableCellWithReuseIdentifier方法,但我使用工具未能找到问题所在。

还有其他可能导致这种情况的因素吗?是否有更快速的方法来准备UICollectionViewCell或以更快的方式进行dequeue


1
使用工具,您是否发现了一个方法调用需要太长时间?例如,对于平滑滚动而言,重复使用一个单元格需要0.02秒的时间太长了。 - Daniel S.
是的。在那之后,我发现方法 [uicollectionview updatevisiblecellsnow] 被调用了很多次。通过谷歌搜索,我找到了这个问题:https://dev59.com/cGQo5IYBdhLWcg3wE8C2。 - Avba
1
尝试将一些单元格的显示相关函数移动到集合视图的willDisplayCell方法中,将其他函数移动到didEndDisplayingCell方法中。 - James Bush
1
这是我最新的一次迭代,实现了完美平滑滚动的集合视图,并具有实时视频预览功能(最多可同时预览16个视频)。它甚至使用了Cover Flow自定义布局和“反射”视图,完美地镜像了视频预览。源代码在这里:http://www.mediafire.com/download/ivecygnlhqxwynr/VideoWallCollectionView.zip - James Bush
6个回答

97

如果有滚动问题,任何人都可以按照此处做。

在你的取消排队之后添加这两行。

cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;

4
抱歉,我该怎么办?你的链接指向一个有很多内容的页面。如果我遇到滚动问题,我应该阅读所有内容吗?还是只有在出现卡顿时才需要阅读? - Daniel S.
我不确定你的问题具体是什么。你可以把你的问题指给我,但在我的情况下,结果是UICollectionView导致了卡顿,而我的代码实际上表现良好。在我的情况下,强制单元格层转换为光栅图解决了这个问题。在其他情况下,您可以尝试使用XCode中的时间工具来了解缓慢的原因。如果是您的代码或某些系统代码引起的。 - Avba
4
@AvnerBarr,感谢您的精彩回答,以及您在其他问题上的回答。我已经加了一点小赏金来代表所有人说声谢谢 :) 干杯 - Fattie
1
但我不会在单元格本身中设置属性,因为栅格化具有您可能不想要的内存/性能影响。但是正如其他人在这里以各种形式提到的那样,主要性能损失源于系统在线程上解压缩UIImage [UIImage image...]。对于大型图像来说,这是代价高昂的(请检查新的iOS-8 api PHImageManager,它可以提供帮助)。在最坏的情况下,我建议在后台线程中强制解压图像,然后再将其分配给UIImageView。 - Avba
1
从我的观察来看,使用PHCachingManager会导致单元格更多的延迟。最好的解决方案是在设置图像后,在图像视图上设置光栅化(这很重要),延迟几乎消失了(同时还使用了苹果示例中的startCaching)。 - Pion
显示剩余6条评论

19

我认为“卡顿”问题来自于UIImage的分配,而不是dequeueReusableCellWithReuseIdentifier方法的任何问题。我建议尝试在后台线程上进行图像分配,看看是否能使事情更加流畅。

-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
  mycell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^(void) {
     // Load image on a non-ui-blocking thread
    UIImage *image = [[UIImage imageWithCGImage:[alassetList objectAtIndex:indexpath.row] thumbnail]];

    dispatch_sync(dispatch_get_main_queue(), ^(void) {
        // Assign image back on the main thread
        mycell.imageView.image = image;
    });
  });

  return mycell;
}

更多详细信息请点击这里:https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html


稍微改进一下,使其更加流畅,并添加自定义视图。如果有任何类似于在集合视图中展示的东西,请尝试展示出来。 - iSrinivasan27

8

使用NSURLConnection的sendAsynchronousRequest:queue:completionHandler:方法加载您的图片。

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    [cell.imageView setImage:[UIImage imageWithData:data]];
}];

1

在属性检查器中勾选剪裁子视图和不透明,并取消分页启用。


0

如果有人在使用PhImageManager,关闭同步可以解决问题。(deliveryMode = .FastFormat也可以提供额外的性能增强,但是缩略图的质量会降低)

    let option = PHImageRequestOptions()
    option.deliveryMode = .Opportunistic
    option.synchronous = false
    PHImageManager().requestImageForAsset(phAsset, targetSize: CGSizeMake(2048, 2048), contentMode: .AspectFit, options: option, resultHandler: { (image, objects) in
        self.imageView.image = image!
    })

0

我遇到了UICollectionView滚动的问题。

对我来说,几乎能完美解决问题的方法是:我使用了90x90的png缩略图填充单元格。几乎可以完美解决问题,只是第一次完整滚动不太流畅,但再也没有崩溃过了...

在我的情况下,单元格大小为90x90。

之前有很多原始的png大小,当png原始大小大于约1000x1000时非常卡顿(在第一次滚动时会崩溃多次)。

因此,我在UICollectionView上选择了90x90(或类似的大小),并显示原始的png图像(无论大小如何)。希望这能帮助其他人。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接