Swift图像放置在错误的单元格中,并在UICollectionview中不断更改

Swift图像放置在错误的单元格中,并在UICollectionview中不断更改,swift,swift3,uiimageview,uicollectionview,Swift,Swift3,Uiimageview,Uicollectionview,我已经搜索过了,但没有找到问题的答案,我正在从internet下载图像并将其放入“收藏”视图中,但当我滚动位置时,即使没有滚动,位置也会发生变化。我的代码如下: override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeue

我已经搜索过了,但没有找到问题的答案,我正在从internet下载图像并将其放入“收藏”视图中,但当我滚动位置时,即使没有滚动,位置也会发生变化。我的代码如下:

  override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)

    var Label = cell.viewWithTag(2) as! UILabel
    Label.text = namesArray[indexPath.row]

    var image = cell.viewWithTag(1) as! UIImageView
    let URLString = imgLink[indexPath.row]
    let imgUrl = URL(string: URLString)

    image.downloadedFrom(url: imgUrl!, contentMode: UIViewContentMode.scaleAspectFit)
    UIimg.insert(image.image!, at: indexPath.row)
    return cell
}


public extension UIImageView {
    func downloadedFrom(url: URL, contentMode mode: UIViewContentMode = .scaleAspectFit) {
        contentMode = mode
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard
                let httpURLResponse = response as? HTTPURLResponse, httpURLResponse.statusCode == 200,
                let mimeType = response?.mimeType, mimeType.hasPrefix("image"),
                let data = data, error == nil,
                let image = UIImage(data: data)
                else { return }
            DispatchQueue.main.async() { () -> Void in
                self.image = image
            }
            }.resume()
    }
    func downloadedFrom(link: String, contentMode mode: UIViewContentMode = .scaleAspectFit) {
        guard let url = URL(string: link) else { return }
        downloadedFrom(url: url, contentMode: mode)
    }
}
更新:


此函数是一个异步函数,需要一些时间才能完成

image.downloadedFrom(url: imgUrl!, contentMode: UIViewContentMode.scaleAspectFit)
所以这条线

UIimg.insert(image.image!, at: indexPath.row)
将在上述函数调用完成图像下载之前运行。这将导致您的问题

downloadedFrom函数应该使用完成处理程序在图像下载后运行一些代码,以使其正常工作

我通常使用下面的函数来获取图像

func getImage(urlString:String, completionHandler:(success:Bool, data:NSData?, errorDescription:String?) -> Void) -> Void {

        let url = NSURL(string: urlString)
        let request = NSMutableURLRequest(URL: url!)

        let task = session.dataTaskWithRequest(request) { (data, response, error) in

            guard let data = data where error == nil else {
                completionHandler(success: false,data: nil, errorDescription: error?.localizedDescription)
                return
            }

            completionHandler(success: true, data: data, errorDescription: nil)
        }

        task.resume()

}
可在tableCell/collectionCell中使用,如下所示:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let photo = fetchedResultsController.objectAtIndexPath(indexPath) as! Photo
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! AlbumCell

        cell.backgroundColor = UIColor.grayColor()
        cell.imageView.image = UIImage(named: "placeholder")

        if let image = photo.image {
            cell.imageView.image = image
        } else {

            VTClient.sharedInstance().getImage(photo.url) { (success:Bool, data:NSData?, errorDescription:String?) in
                if success {

                    dispatch_async(dispatch_get_main_queue()) {
                        let image = UIImage(data: data!)
                        cell.imageView.image = image
                        FlickrClient.Caches.imageCache.storeImage(image, withIdentifier: photo.id)
                    }
                }
            }
        }

        return cell
    }
}

有关如何使用此功能的更多信息,请参见我的项目。

您需要研究单元重用。您将单元格上的图像视图设置为特定图像,然后当您滚动该单元格时,该单元格将被重新使用,因此现在有不正确的图像。将数据图像与UI单元格分开,只需从数据中刷新单元格即可。indexpath代码中的行单元格是正确的。您只需要将图像下载到后台线程中。使用这个库。它将在后台加载图像,并缓存您的图像。例如:image.sd_setImagewith:URLstring:NSURL,占位符image:uiImageName:我不需要使用库来下载图像让session=urlsession.shared。这段代码是一个比较老的项目,Swift 2我想,可能需要一些轻微的改动,我应该解释得更好一些。这是我在学习iOS时参与的一个项目,你不需要这些课程。VTClient就是我放getImage函数的地方,你可以把它放在任何地方。这些类是特定于我的项目的。Photo类只是一个数据类,FlickrClient从FlickrAPI获取图像数据。我在该类中使用图像缓存来存储图像,以便更快地加载。您不必这样做,但这将有助于提高性能。如果您想使用我的代码,您需要使用我的代码的部分。我只是展示了我的代码,以显示它将是如何做你没有照片类,你不需要那个部分。显示更新的代码代码代码现在看起来应该可以了,您现在遇到了什么问题?使用此代码:var image=cell.viewWithTag1 as!UIImageView let URLString=imgLink[indepath.row]let imgUrl=URLString:URLString您可以添加printindexPath.row、URLString并查看控制台的输出结果吗
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {

        let photo = fetchedResultsController.objectAtIndexPath(indexPath) as! Photo
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! AlbumCell

        cell.backgroundColor = UIColor.grayColor()
        cell.imageView.image = UIImage(named: "placeholder")

        if let image = photo.image {
            cell.imageView.image = image
        } else {

            VTClient.sharedInstance().getImage(photo.url) { (success:Bool, data:NSData?, errorDescription:String?) in
                if success {

                    dispatch_async(dispatch_get_main_queue()) {
                        let image = UIImage(data: data!)
                        cell.imageView.image = image
                        FlickrClient.Caches.imageCache.storeImage(image, withIdentifier: photo.id)
                    }
                }
            }
        }

        return cell
    }
}