我使用Alamofire库在collectionView中显示单元格中的图像 但我的问题是当我向上滚动&& down,我的CollectionView在单元格中显示错误的图像
这是我设置单元格数据的代码段
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! CardViewCell
let pos = indexPath.item % 5
var paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 2.5
paragraphStyle.alignment = .Right
paragraphStyle.lineBreakMode = .ByTruncatingTail
if let text = currentCollection.titles?[indexPath.item] {
var attrString = NSMutableAttributedString(string: text)
attrString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range:NSMakeRange(0, attrString.length))
cell.title.attributedText = attrString
} else {
cell.title.text = currentCollection.titles?[indexPath.item]
}
if let catId = currentCollection.catIds?[indexPath.item] {
cell.iconImage.image = UIImage(named: icons[catId-1])
}
cell.title.font = UIFont(name: "B Yekan", size: 14)
cell.title.preferredMaxLayoutWidth = cell.frame.size.width - 48
cell.iconImage.image = cell.iconImage.image!.imageWithRenderingMode(.AlwaysTemplate)
cell.iconImage.tintColor = UIColor.whiteColor()
let imageUrl = currentCollection.urlImages![indexPath.item]
if let image = currentCollection.imageCache.objectForKey(imageUrl) as? UIImage {
cell.backImage.image = image
} else {
cell.backImage.image = nil
cell.request = Alamofire.request(.GET, imageUrl).validate(contentType: ["image/*"]).responseImage() {
(request, _, image, error) in
if error == nil && image != nil {
self.currentCollection.imageCache.setObject(image!, forKey: request.URLString)
cell.backImage.image = image
}
}
}
cell.layer.shadowPath = UIBezierPath(roundedRect: cell.bounds, cornerRadius: cell.layer.cornerRadius).CGPath
if indexPath.item == currentCollection.titles!.count-3 {
currentCollection.page++
appendTitlesInPage(currentCollection.page)
}
return cell
}
可以帮助我哪里出错了?请!
答案 0 :(得分:1)
图像请求需要时间 - 在此期间,请求保留对单元格的引用,并在请求完成后设置单元格backImage.image
。不幸的是,到那时,单元格可能已经在屏幕外滚动,并且可能正在另一个indexPath处重新使用,其中图像是不正确的。相反,您应该使用表格视图的cellForItemAtIndexPath
方法来获取正确的单元格(如果单元格不再可见,则返回nil将阻止您的错误。)
答案 1 :(得分:1)
https://github.com/gchiacchio/AlamoImage
正如@johnpatrickmorgan所说,问题是:当您滚动单元格时会被重复使用,并且当图像请求得到响应时,它将不再有效(图像和单元格不再有效)匹配)。
由于响应时间由网络条件决定,您只能等待响应,但您可以做的是在您知道将重用该单元时取消正在进行的请求。为此,您可以在设置新图像之前设置cell.request?.cancel()
,如下所示:
let imageUrl = currentCollection.urlImages![indexPath.item]
//Cancel the request in progress (to a wrong image) if any.
cell.request?.cancel()
if let image = currentCollection.imageCache.objectForKey(imageUrl) as? UIImage {
cell.backImage.image = image
} else {
cell.backImage.image = nil
cell.request = Alamofire.request(.GET, imageUrl).validate(contentType: ["image/*"]).responseImage() {
(request, _, image, error) in
if error == nil && image != nil {
self.currentCollection.imageCache.setObject(image!, forKey: request.URLString)
cell.backImage.image = image
}
}
}
答案 2 :(得分:0)
看看" LazyTableImages" Apple提供的示例应用程序。它带有UITableView
,但它与UICollectionView
基本上是相同的代码,并且您不需要第三方库来执行此操作。
IconDownloader *iconDownloader = (self.imageDownloadsInProgress)[indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[IconDownloader alloc] init];
iconDownloader.appRecord = appRecord;
[iconDownloader setCompletionHandler:^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
// Display the newly loaded image
cell.imageView.image = appRecord.appIcon;
// Remove the IconDownloader from the in progress list.
// This will result in it being deallocated.
[self.imageDownloadsInProgress removeObjectForKey:indexPath];
}];
(self.imageDownloadsInProgress)[indexPath] = iconDownloader;
[iconDownloader startDownload];
您的相关部分位于完成处理程序中,您可以使用cellForRowAtIndexPath
获取单元格。这个(以及相应的集合视图方法)确保您获得正确的单元格,如果它在屏幕外,它将返回nil并且一切都会正常降级。