简体   繁体   中英

request.cancel() for reused cell Alamofire swift

I have a collection view with images, I am using Alamofire and AlamofireImage for the networking code. At the beginning of the cellForItemAtIndexPath I set the image to nil and cancel any in-flight request if one exists, using request?.cancel(). But doing so, some cells won't be populated with images at all. Can you show me what I am doing wrong? See my cellForItemAtIndexPath code below:

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! StoreCell

    let entry = self.dataCell.addCell[indexPath.section][indexPath.item]

    stringURL = "https://website.com/stories_db/images/\(entry.filename)"

    cell.title.text = entry.title
    cell.subTitle.text = entry.author
    cell.cost.text = entry.cost

    // Reset the cell
    cell.storyImage.image = nil
//  request?.cancel()

    if let image = dataCell.cachedImage(stringURL) {
        cell.storyImage.image = image
    } else {
        request = dataCell.getNetworkImage(stringURL) { image in
            cell.storyImage.image = image
        }
    }

    // Fix the collection view cell in size
    cell.contentView.frame = cell.bounds
    cell.contentView.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]

    return cell
}

It looks like you're reusing a single var called request to store the image request. If more than one of your collection view cells is visible at a time, you may need to make more that one async image request at a time, so you need a way to store multiple in-progress requests.

For example, if your collection view has three cells and all are visible, when it reloads it will call cellForItemAtIndexPath to get the first cell. Your code creates the cell and kicks off the async request for "Image 1" and stores it in your request var.

Then the collection view immediately calls cellForItemAtIndexPath again to get the second cell. If the request for "Image 1" is still in progress, calling request?.cancel() interrupts it so "Image 1" will never finish downloading. The code then creates a new request for "Image 2" and assigns it to request.

The collection view immediately calls cellForItemAtIndexPath to get the third cell...

One solution would be to store an array (or dictionary) of active requests. Add a request when you make it, remove it when the request completes (failure or success). Then if you determine that there's a request in progress for a cell you're about to reuse, cancel that request and remove it from the list.

Another way to do it would be to create a custom cell subclass and have it store the active request. This has the advantage of making it simpler to correlate requests to cells.

Using either approach, you may want to consider cancelling the active request for a cell in UICollectionViewCell.prepareForReuse() instead of cellForItemAtIndexPath.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM