gpt4 book ai didi

ios - 如何获得包含大量图像(50-200)的活泼的 UICollectionView?

转载 作者:技术小花猫 更新时间:2023-10-29 10:26:38 24 4
gpt4 key购买 nike

我在一个显示大量照片 (50-200) 的应用程序中使用 UICollectionView 并且我在让它变得活泼时遇到了问题(例如像照片应用程序一样活泼).

我有一个自定义 UICollectionViewCell 和一个 UIImageView 作为它的 subview 。我使用 UIImage.imageWithContentsOfFile: 从文件系统加载图像到单元格内的 UIImageViews。

我现在已经尝试了很多方法,但它们不是有问题就是有性能问题。

注意:我正在使用 RubyMotion,因此我将以 Ruby 风格编写所有代码片段。

首先,这是我自定义的 UICollectionViewCell 类以供引用...

class CustomCell < UICollectionViewCell
def initWithFrame(rect)
super

@image_view = UIImageView.alloc.initWithFrame(self.bounds).tap do |iv|
iv.contentMode = UIViewContentModeScaleAspectFill
iv.clipsToBounds = true
iv.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth
self.contentView.addSubview(iv)
end

self
end

def prepareForReuse
super
@image_view.image = nil
end

def image=(image)
@image_view.image = image
end
end

方法 #1

保持简单..

def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
image_path = @image_paths[index_path.row]
cell.image = UIImage.imageWithContentsOfFile(image_path)
end

使用这个向上/向下滚动很糟糕。它跳跃而缓慢。

方法 #2

通过 NSCache 添加一点缓存...

def viewDidLoad
...
@images_cache = NSCache.alloc.init
...
end

def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
image_path = @image_paths[index_path.row]

if cached_image = @images_cache.objectForKey(image_path)
cell.image = cached_image
else
image = UIImage.imageWithContentsOfFile(image_path)
@images_cache.setObject(image, forKey: image_path)
cell.image = image
end
end

同样,在第一个完整卷轴上跳动缓慢,但从那时起就一帆风顺了。

方法 #3

异步加载图像...(并保留缓存)

def viewDidLoad
...
@images_cache = NSCache.alloc.init
@image_loading_queue = NSOperationQueue.alloc.init
@image_loading_queue.maxConcurrentOperationCount = 3
...
end

def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
image_path = @image_paths[index_path.row]

if cached_image = @images_cache.objectForKey(image_path)
cell.image = cached_image
else
@operation = NSBlockOperation.blockOperationWithBlock lambda {
@image = UIImage.imageWithContentsOfFile(image_path)
Dispatch::Queue.main.async do
return unless collectionView.indexPathsForVisibleItems.containsObject(index_path)
@images_cache.setObject(@image, forKey: image_path)
cell = collectionView.cellForItemAtIndexPath(index_path)
cell.image = @image
end
}
@image_loading_queue.addOperation(@operation)
end
end

这看起来很有希望,但有一个我无法追踪的错误。在初始 View 加载时,所有图像都是相同的图像,并且当您滚动整个 block 时,会加载另一个图像,但所有图像都有该图像。我试过调试它,但我无法弄明白。

我也尝试用 Dispatch::Queue.concurrent.async { ... } 替换 NSOperation,但这似乎是一样的。

如果我能让它正常工作,我认为这可能是正确的方法。

方法 #4

沮丧的是,我决定将所有图像预加载为 UIImages...

def viewDidLoad
...
@preloaded_images = @image_paths.map do |path|
UIImage.imageWithContentsOfFile(path)
end
...
end

def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
cell.image = @preloaded_images[index_path.row]
end

事实证明,在第一个完整滚动中,这有点缓慢和跳跃,但之后一切都很好。

总结

所以,如果有人能指出正确的方向,我将不胜感激。照片应用如何做到如此出色


其他人请注意:[接受的] 答案解决了我的图像出现在错误单元格中的问题,但即使在将图像调整为正确尺寸后,我的滚动仍然不稳定。在将我的代码剥离到最基本的部分之后,我最终发现 UIImage#imageWithContentsOfFile 是罪魁祸首。尽管我使用这种方法预热了 UIImages 的缓存,但 UIImage 似乎在内部进行了某种惰性缓存。更新我的缓存预热代码以使用此处详述的解决方案后 - stackoverflow.com/a/10664707/71810 - 我终于拥有了 super 流畅的 ~60FPS 滚动。

最佳答案

我认为方法 #3 是最好的方法,我想我可能已经发现了这个错误。

您在操作 block 中分配给@image,这是整个 Collection View 类的私有(private)变量。您可能应该更改:

@image = UIImage.imageWithContentsOfFile(image_path)

image = UIImage.imageWithContentsOfFile(image_path)

并更改所有对 @image 的引用以使用局部变量。我敢打赌,问题是每次您创建一个操作 block 并分配给实例变量时,您都会替换已经存在的内容。由于操作 block 出队方式的一些随机性,主队列异步回调正在取回相同的图像,因为它正在访问上次分配的 @image

本质上,@image 就像操作和异步回调 block 的全局变量。

关于ios - 如何获得包含大量图像(50-200)的活泼的 UICollectionView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13864958/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com