swift iOS – 快速滚动后混合的UICollectionView图像

swift iOS – 快速滚动后混合的UICollectionView图像,第1张

概述我是 swift和iOS编程的新手,但我已经能够在 Xcode中为我的应用程序构建一个基本稳定的启动界面. CollectionView从我家庭网络服务器上的csv文件创建的字典数组中获取图像和文本. cvs文件包含以下格式的数据(注意,已更改URL以保护许可图像): csv文件 csv file is @ url https://myserver.com/csv.txt and contains 我是 swift和iOS编程的新手,但我已经能够在 Xcode中为我的应用程序构建一个基本稳定的启动界面. CollectionVIEw从我家庭网络服务器上的csv文件创建的字典数组中获取图像和文本. cvs文件包含以下格式的数据(注意,已更改URL以保护许可图像):

csv文件

csv file is @ url https://myserver.com/csv.txt and contains the followingTitle";"SerIEsImageURLTitle1";"https://licensedimage.com/url1Title2";"https://licensedimage.com/url2...Title1000";"https://licensedimage.com/url1000

问题是当快速滚动CollectionVIEw时,单元格将抓取不正确的图像.值得注意的是,如果您进行慢速或中速滚动,则在将正确的图像渲染到正确的单元格之前将显示不同的图像(单元格的标签文本始终是正确的,只有图像永远关闭).在图像与具有标签的正确单元格不匹配之后,CollectionVIEw中的所有其他单元格也将显示不正确的图像.

例如.单元格1-9将显示具有正确Image1-9的Title1-9
当缓慢滚动时,单元格19-27将显示标题19-27,将简要显示图像10-18,然后显示正确的图像19-27.
当快速滚动大量单元格时(例如从单元格1-9到单元格90-99),单元格90-99将显示标题90-99,将显示图像10-50ish,然后将错误地保留在图像41-50 (或左右).当进一步滚动时,单元格100将显示正确的标题,但仅显示图像41-50范围内的图像.

我认为这个错误或者是因为没有正确处理单元重用,没有正确处理图像的缓存,或者两者兼而有之.它也可能是我作为初学者iOS / swift程序员看不到的东西.我试图用完成修饰符实现一个请求,但似乎无法使我的代码设置方式正常工作.我将不胜感激任何帮助,并解释为什么修复工作的方式.谢谢!

相关代码如下.

SerIEsCollectionVIEwController.swift

class SerIEsCollectionVIEwController: UICollectionVIEwController,UISearchbarDelegate {let reuseIDentifIEr:String = "SerIEsCell"// Set Data Source Models & Variablesstruct serIEsModel {    let Title: AnyObject    let serIEsimageurl: AnyObject}var serIEsDict = [String:AnyObject]()var serIEsArray = [serIEsModel]()// Image Cachevar imageCache = NSCache() overrIDe func vIEwDIDLoad() {    super.vIEwDIDLoad()    // Grab Data from Source    do {        let url = NSURL(string: "https://myserver.com/csv.txt")        let fullText = try Nsstring(contentsOfURL: url!,enCoding: NSUTF8StringEnCoding)        let readings = fullText.componentsSeparatedByString("\n") as [String]        var serIEsDictCount = readings.count        serIEsDictCount -= 1        for i in 1..<serIEsDictCount {            let serIEsData = readings[i].componentsSeparatedByString("\";\"")            serIEsDict["Title"] = "\(serIEsData[0])"            serIEsDict["SerIEsImageURL"] = "\(serIEsData[1])"            serIEsArray.append(serIEsModel(                Title: serIEsDict["Title"]!,serIEsimageurl: serIEsDict["SerIEsImageURL"]!,))        }    } catch let error as NSError {        print("Error: \(error)")    }}overrIDe func dIDReceiveMemoryWarning() {    super.dIDReceiveMemoryWarning()    imageCache.removeAllObjects()    // dispose of any resources that can be recreated.}//...//...skipPing over some stuff that isn't relevant//...overrIDe func collectionVIEw(collectionVIEw: UICollectionVIEw,cellForItemAtIndexPath indexPath: NSIndexPath) -> SerIEsCollectionVIEwCell {    let cell: SerIEsCollectionVIEwCell = collectionVIEw.dequeueReusableCellWithReuseIDentifIEr(reuseIDentifIEr,forIndexPath: indexPath) as! SerIEsCollectionVIEwCell    if (self.searchBaractive) {        let serIEs = serIEsArrayForSearchResult[indexPath.row]        do {            // set image            if let imageURL = NSURL(string: "\(serIEs.serIEsimageurl)") {                if let image = imageCache.objectForKey(imageURL) as? UIImage {                        cell.serIEsImage.image = image                } else {                    dispatch_async(dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_BACKGROUND,0),{                        if let tvimageData = NSData(contentsOfURL: imageURL) {                            let image = UIImage(data: tvimageData)                            self.imageCache.setobject(image!,forKey: imageURL)                                dispatch_async(dispatch_get_main_queue(),{ () -> VoID in                                    cell.serIEsImage.image = nil                                    cell.serIEsImage.image = image                                })                        }                    })                }            }            cell.serIEsLabel.text = "\(serIEs.Title)"        }    } else {        let serIEs = serIEsArray[indexPath.row]        do {            // set image            if let imageURL = NSURL(string: "\(serIEs.serIEsimageurl)") {                if let image = imageCache.objectForKey(imageURL) as? UIImage {                        cell.serIEsImage.image = image                } else {                    dispatch_async(dispatch_get_global_queue(disPATCH_QUEUE_PRIORITY_BACKGROUND,forKey: imageURL)                            dispatch_async(dispatch_get_main_queue(),{ () -> VoID in                                cell.serIEsImage.image = nil                                cell.serIEsImage.image = image                            })                        }                    })                }            }            cell.serIEsLabel.text = "\(serIEs.Title)"        }    }    cell.layer.shouldRasterize = true    cell.layer.rasterizationScale = UIScreen.mainScreen().scale    cell.prepareForReuse()    return cell}

SerIEsCollectionVIEwCell

class SerIEsCollectionVIEwCell: UICollectionVIEwCell {@IBOutlet weak var serIEsImage: UIImageVIEw!@IBOutlet weak var serIEsLabel: UILabel!}
您需要了解dequeue如何正常工作.有很好的文章.

总结一下:

To maintain scrolling smoothness,dequeue is used which essentially
reuses cells after a certain limit. Say you have 10 visible cells at a
time,it will likely create 16-18 (3-4 above,3-4 below,just rough
estimates) cells only,even though you might need 1000 cells.

现在,当你这样做时 –

let cell: SerIEsCollectionVIEwCell = collectionVIEw.dequeueReusableCellWithReuseIDentifIEr(reuseIDentifIEr,forIndexPath: indexPath) as! SerIEsCollectionVIEwCell

您正在重用已经制作的单元格中的现有单元格.这就是为什么你会看到旧图像一段时间然后在加载后看到新图像的原因.

您需要在单元格出列后立即清除旧图像.

cell.serIEsImage.image = UIImage()    //nil

实际上,您将在图像中以这种方式设置一个空白占位符,而不是在您的情况下将imageCache设置为nil.

这解决了这个问题 –

Noticeably,if you do a slow or medium scroll,a different image will show before the correct image is rendered into the correct cell (the label text for the cells are always correct,only the image is ever off).

现在,在为当前单元格分配图像时,如果要分配的图像属于此单元格,则需要再次检查.您需要检查这一点,因为您正在重新分配它的图像视图,它可能与indexPath上的单元格关联,而不是生成图像加载请求时的单元格.

当您将单元格出列并将image属性设置为nil时,请让serIEsImage为您记住当前的indexPath.

cell.serIEsImage.indexPath = indexPath

稍后,如果imageVIEw仍属于先前分配的indexPath,则仅将图像分配给它.这与细胞重用100%有效.

if cell.serIEsImage.indexPath == indexPathcell.serIEsImage.image = image

您可能需要考虑在UIImageVIEw实例上设置indexPath.这是我准备并用于类似场景的东西 –
UIView-Additions

它既有Objective-C又有.迅速.

总结

以上是内存溢出为你收集整理的swift iOS – 快速滚动后混合的UICollectionView图像全部内容,希望文章能够帮你解决swift iOS – 快速滚动后混合的UICollectionView图像所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1031206.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-23
下一篇2022-05-23

发表评论

登录后才能评论

评论列表(0条)

    保存