我使用Alamofire库在collectionView的单元格中显示图像,但我的问题是当我向上和向下滚动时,我的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
}能帮我哪里错了吗?请!
发布于 2015-05-30 00:45:07
图像请求需要时间-在这段时间内,请求保留对单元格的引用,并在请求完成后设置单元格的backImage.image。不幸的是,到那时,单元格可能已经滚动到屏幕之外,并且可能在另一个indexPath上被重用,其中的图像是不正确的。相反,您应该使用表视图的cellForItemAtIndexPath方法来获取正确的单元格(如果该单元格不再可见,这将返回nil,这将防止您出错)。
发布于 2015-06-04 02:55:51
编辑:现在我已经开发了一个小的CocoaPods库来无缝地处理这个问题。我建议你使用这个,我已经在几个项目中运行了它,没有任何问题。
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
}
}
}发布于 2015-06-04 03:09:42
看看苹果公司提供的"LazyTableImages“示例应用程序。它有一个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,并且所有内容都会正常降级。
https://stackoverflow.com/questions/30534544
复制相似问题