
我有一个自定义UICollectionVIEwCell与UIImageVIEw作为子视图.我正在使用UIImage.imageWithContentsOffile :,将文件系统中的图像加载到单元格内的UIImageVIEw中.
我现在已经尝试了很多方法,但是它们已经是BUG或者性能问题.
注意:我使用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 endend
方法#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 ...enddef collectionVIEw(collection_vIEw,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 endend
再次,第一个完整的滚动跳跃和缓慢,但从那以后,它是顺利的航行.
方法#3
加载图像异步…(并保持缓存)
def vIEwDIDLoad ... @images_cache = NSCache.alloc.init @image_loading_queue = NSOperationQueue.alloc.init @image_loading_queue.maxConcurrentoperationCount = 3 ...enddef collectionVIEw(collection_vIEw,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) endend 这看起来很有希望,但是有一个我无法追踪的错误.在初始视图加载时,所有图像都是相同的图像,当您滚动整个块加载与另一个图像,但都具有该图像.我试过调试,但我无法想像出来.
我也尝试用dispatch :: Queue.concurrent.async {…}替换NSOperation,但是似乎是一样的.
我认为这可能是正确的方法,如果我能让它正常工作.
方法#4
在沮丧中,我决定将所有图像预先加载为UIImages …
def vIEwDIDLoad ... @preloaded_images = @image_paths.map do |path| UIImage.imageWithContentsOffile(path) end ...enddef collectionVIEw(collection_vIEw,forIndexPath: index_path) cell.image = @preloaded_images[index_path.row]end
在第一个完整的卷轴中,结果变得有点慢,跳跃,但一切顺利.
概要
所以,如果有人能指出我正确的方向,我会非常感激.照片应用程序如何做得很好?
注意其他人:[被接受]的答案解决了我的图像出现在错误的单元格的问题,但即使在调整我的图像大小以正确的大小后,我仍然正在滚动滚动.在将我的代码剥离到裸机之后,我最终发现UIImage#imageWithContentsOffile是罪魁祸首.即使我使用这种方法预热了UIImages的缓存,UIImage似乎在内部做一些懒惰的缓存.更新我的缓存加温代码以使用这里详细说明的解决方案 – stackoverflow.com/a/10664707/71810 – 我终于有超级光滑〜60FPS滚动.
解决方法 我认为#3方法是最好的方法,我想我可能会发现这个BUG.您在 *** 作块中为@image分配整个集合视图类的私有变量.你应该改变:
@image = UIImage.imageWithContentsOffile(image_path)
至
image = UIImage.imageWithContentsOffile(image_path)
并更改@image的所有引用以使用局部变量.我愿意打赌,问题是每次创建一个 *** 作块并分配给实例变量时,你正在替换已经存在的内容.由于 *** 作块出现的一些随机性,主队列异步回调正在获得相同的图像,因为它正在访问最后一次@image被分配.
本质上,@image像 *** 作和异步回调块的全局变量一样.
总结以上是内存溢出为你收集整理的ios – 如何获得许多图像的快速UICollectionView(50-200)?全部内容,希望文章能够帮你解决ios – 如何获得许多图像的快速UICollectionView(50-200)?所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)