为啥在 URLSessionTask 完成后 indexPath 会发生变化?

Posted

技术标签:

【中文标题】为啥在 URLSessionTask 完成后 indexPath 会发生变化?【英文标题】:Why indexPath can change after a URLSessionTask finishes?为什么在 URLSessionTask 完成后 indexPath 会发生变化? 【发布时间】:2020-07-22 10:38:00 【问题描述】:

我正在学习 ios 编码和阅读一本书。 UICollectionViewCell 的 indexPath 有一些我不明白的地方。 UICollectionView 显示使用带有 URLSessionDataTask 的 Photo 对象的 remoteUrl 属性获取的图像。将转义的完成处理程序传递给图像获取函数以更新单元格内的 UIImageView。

书上代码 sn-p 的注释说“照片的索引路径可能在请求开始和完成之间发生了变化”。为什么会这样?

func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) 
    let photo = photoDataSource.photos[indexPath.row]
    
    // Download the image data, which could take some time
    photoStore.fetchImage(photo: photo)  (result) in
        
        // The index path for the photo might have changed between the
        // time the request started and finished, so find the most
        // recent index path
        guard
            let photoIndex = self.photoDataSource.photos.firstIndex(of: photo),
            case let .success(image) = result
        else 
            return
        
        
        let photoIndexPath = IndexPath(row: photoIndex, section: 0)
        
        // When the request finishes, only update the cell if it's still visible
        if let cell = collectionView.cellForItem(at: photoIndexPath) as? PhotoCollectionViewCell 
            cell.updateImage(image: image)
        
    

【问题讨论】:

您缺少UITableViewUICollectionView 的重用概念。细胞被重复使用。 【参考方案1】:

了解tableView 或collectionView 的重用单元

示例: 添加代码 在viewDidLoad:

collectionView.register(UICollectionViewCell.self, forCellReuseIdentifier: "Your Reuse Identifier")

在您的 viewController (UICollectionViewDelegateFlowLayout) 的 Extension

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Your Reuse Identifier", for: indexPath)
    cell.imageView.image = photos[indexPath.row]
    return cell

【讨论】:

以上是关于为啥在 URLSessionTask 完成后 indexPath 会发生变化?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不需要释放静态数组?

为啥在 Play 2.3 项目中 sbt 编译后 sbt 失败并显示 NoClassDefFoundError: play/Play$ in Play 2.2.x 项目?

请求完成后触发 Redux 异步操作。为啥?

Python:为啥弹出队列比 for-in 块更快?

oracle数据库的存储过程中可以用到隐形游标。但是我不太明白为啥可以用 for in loop来完成对数据的处理。

为啥在停止应用程序并再次运行后,之前完成的下载会触发?