使用Alamofire在ios

时间:2015-05-29 16:26:13

标签: ios swift uicollectionview alamofire

我使用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
}

可以帮助我哪里出错了?请!

3 个答案:

答案 0 :(得分:1)

图像请求需要时间 - 在此期间,请求保留对单元格的引用,并在请求完成后设置单元格backImage.image。不幸的是,到那时,单元格可能已经在屏幕外滚动,并且可能正在另一个indexPath处重新使用,其中图像是不正确的。相反,您应该使用表格视图的cellForItemAtIndexPath方法来获取正确的单元格(如果单元格不再可见,则返回nil将阻止您的错误。)

答案 1 :(得分:1)

编辑:现在我开发了一个小型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
        }
    }
}

答案 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并且一切都会正常降级。