【问题标题】:CollectionView duplicate cell when loading more data加载更多数据时 CollectionView 重复单元格
【发布时间】:2016-02-13 23:23:47
【问题描述】:

问题:

我有一个 CollectionView,它将 UIimage 加载到每个单元格中。但是我的问题是,当我加载带有更多图像的其他单元格时,它们似乎重复了。我不太明白我的代码中可能导致这种情况的原因。 可能是因为可重复使用的细胞有问题吗?

谁能明白为什么会这样?

注意:包含图像的数组没有重复项

问题视频: https://www.youtube.com/watch?v=vjRsFc8DDmI

问题图片:

这是我的 collectionView 函数:

func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    //#warning Incomplete method implementation -- Return the number of items in the section
    if self.movies == nil
    {
      return 0

    }

    return self.movies!.count

}

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

   if self.movies != nil && self.movies!.count >= indexPath.row
    {
        // Calc size of cell
        cell.frame.size.width = screenWidth / 3
        cell.frame.size.height = screenWidth / 3 * 1.54

        let movies = self.movies![indexPath.row]
        if(movies.posterPath != "" || movies.posterPath != "null"){
        cell.data = movies.posterPath
        }
        else{
        cell.data = nil
        }
        // See if we need to load more movies
        let rowsToLoadFromBottom = 5;
        let rowsLoaded = self.movies!.count
        if (!self.isLoadingMovies && (indexPath.row >= (rowsLoaded - rowsToLoadFromBottom)))
        {
            let totalRows = self.movieWrapper!.totalResults!
            let remainingMoviesToLoad = totalRows - rowsLoaded;
            if (remainingMoviesToLoad > 0)
            {
                self.loadMoreMovies()
            }
        }
}
   else
{
        cell.data = nil
}

    return cell
}

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize
{
    return CGSize(width: screenWidth/3, height: screenWidth/3*1.54)
}

这里我从 Wrapper 类加载数据:

func loadFirstMovies()
{

    isLoadingMovies = true

    Movies.getMovies({ (movieWrapper, error) in
        if error != nil
        {
            // TODO: improved error handling
            self.isLoadingMovies = false
            let alert = UIAlertController(title: "Error", message: "Could not load first movies \(error?.localizedDescription)", preferredStyle: UIAlertControllerStyle.Alert)
            alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
            self.presentViewController(alert, animated: true, completion: nil)
        }
        self.addMoviesFromWrapper(movieWrapper)
        self.activityIndicator.hidden = true
        self.isLoadingMovies = false
        self.collectionView.reloadData()
    })
}

func loadMoreMovies(){

    self.isLoadingMovies = true
    if self.movies != nil && self.movieWrapper != nil && self.movieWrapper!.page < self.movieWrapper!.totalPages
    {
        // there are more species out there!
        Movies.getMoreMovies(self.movieWrapper, completionHandler: { (moreWrapper, error) in
            if error != nil
            {
                // TODO: improved error handling
                self.isLoadingMovies = false
                let alert = UIAlertController(title: "Error", message: "Could not load more movies \(error?.localizedDescription)", preferredStyle: UIAlertControllerStyle.Alert)
                alert.addAction(UIAlertAction(title: "Click", style: UIAlertActionStyle.Default, handler: nil))
                self.presentViewController(alert, animated: true, completion: nil)
            }
            print("got more!")
            self.addMoviesFromWrapper(moreWrapper)
            self.isLoadingMovies = false
            self.collectionView.reloadData()
        })
    }
}

func addMoviesFromWrapper(wrapper: MovieWrapper?)
{
    self.movieWrapper = wrapper
    if self.movies == nil
    {
        self.movies = self.movieWrapper?.results
    }
    else if self.movieWrapper != nil && self.movieWrapper!.results != nil
    {
        self.movies = self.movies! + self.movieWrapper!.results!
    }
}

最后我打电话给:loadFirstMovies()viewDidLoad()

编辑: 即将到来的CollectionViewCell

class UpcomingCollectionViewCell: UICollectionViewCell {

@IBOutlet weak var imageView: UIImageView!


var data:String?{
    didSet{
        self.setupData()
    }
}

func setupData(){

   self.imageView.image = nil // reset the image

    if let urlString = data{
        let url =  NSURL(string: "http://image.tmdb.org/t/p/w342/" + urlString)
        self.imageView.hnk_setImageFromURL(url!)


      }
    }  
 }

【问题讨论】:

  • 请出示您的UpcomingCollectionViewCell的代码...
  • 我已经用 UpcomingCollectionViewCell 更新了问题

标签: ios swift uiimageview collectionview


【解决方案1】:

这是一个典型的表格视图/集合视图设置问题。

每当您使用像dequeueReusableCellWithReuseIdentifier: 这样的出队方法回收单元格时,您必须始终完全配置单元格中的所有视图,包括将所有文本字段/图像视图设置为其起始值。您的代码有几个 if 语句,如果 if 的条件为假,则您无需在单元格中设置视图。您需要使用 else 子句从单元格的视图中清除旧内容,以防最后一次使用单元格时留下内容。

编辑:

将您的 cellForItemAtIndexPath 方法更改为这样开始:

func collectionView(collectionView: UICollectionView, 
  cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
{
    let cell =    
      collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, 
        forIndexPath: indexPath) as! UpcomingCollectionViewCell
    cell.imageView.image = nil;  //Remove the image from the recycled cell
//The rest of your method ...

【讨论】:

  • 我已经用“cellForItemAtIndexPath”中的 else 语句编辑了答案,它仍然会导致某些单元格被复制。但是与以前相比(没有其他)不会经常发生吗?
  • 要完成这项工作,您还需要 André Slotta 对 setupData 的更改(在加载新图像之前将 imageView 的图像设置为 nil。)
  • 我也添加了“André Slotta”的更改,但单元格现在是空的并且没有加载新图像。我制作了一个关于其当前状态的短视频,请参阅:youtube.com/watch?v=vjRsFc8DDmI。代码也更新了
  • 这成功了!但我不明白为什么它以前不起作用:)
  • 仔细阅读我原来的答案。我告诉你你需要做什么。 您必须始终完全配置回收的单元格。 尽管您的代码没有配置路径,但在这些情况下,上次使用该单元格时留下的图像仍将位于回收的单元格中.在我添加的代码中,我在开始 if 语句之前明确地将单元格的 imageView.image 设置为 nil。这样,无论代码如何通过您的 if 语句,图像视图总是以 nil 开始。
【解决方案2】:

在您的自定义单元格setupData() 方法中尝试以下操作:

func setupData(){
  self.imageView.image = nil // reset the image

  if let urlString = data{
    let url =  NSURL(string: "http://image.tmdb.org/t/p/w342/" + urlString)
    self.imageView.hnk_setImageFromURL(url!)
  }
}

【讨论】:

  • 这会清除单元格图像,但会导致某些单元格为空。
  • 好吧...如果有一个urlString 指向一个实际的图像文件并且hnk_setImageFromURL 方法按预期工作,那么这段代码肯定可以工作。
  • hnk_setImageFromURL 来自“Haneke”库,所以我希望它可以工作并且 urlString 也会导致一个实际的图像文件?
  • 您首先要清除图像,然后在加载后让 hnk_setImageFromURL 调用安装图像。
猜你喜欢
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
相关资源
最近更新 更多