加载更多数据时,CollectionView重复单元格 [英] CollectionView duplicate cell when loading more data

查看:63
本文介绍了加载更多数据时,CollectionView重复单元格的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:



我有一个CollectionView,它将UIimage加载到每个单元格中。但是我的问题是,当我用更多图像加载其他单元时,它们似乎重复。我在代码中看不到是什么原因造成的。
可能是由于可重复使用的单元格出现了问题吗?



任何人都可以看到发生这种情况的原因吗?



注意:图片没有重复



问题视频:



以下是我的collectionView函数:

  func collectionView(collectionView:UICollectionView,numberOfItemsInSection部分:Int)-> Int {
//#warning方法实现不完善-如果self.movi​​es == nil
{
返回0
$,则返回
节中的项目数b $ b}

return self.movi​​es!.count

}

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

如果self.movi​​es!= nil&& self.movi​​es!.count> = indexPath.row
{
//计算单元格大小
cell.frame.size.width = screenWidth / 3
cell.frame。 size.height = screenWidth / 3 * 1.54

让电影= self.movi​​es![indexPath.row]
if(movies.posterPath!= || movie.posterPath!= null){
cell.data = movie.posterPath
}
else {
cell.data = nil
}
//查看是否需要加载更多电影
让rowsToLoadFromBottom = 5;
让rowsLoaded = self.movi​​es!.count
if(!self.isLoadingMovies&&(indexPath.row> =(rowsLoaded-rowsToLoadFromBottom)))
{
让totalRows = self.movi​​eWrapper!.totalResults!
让maintainMoviesToLoad = totalRows-rowsLoaded;
if(remainingMoviesToLoad> 0)
{
self.loadMoreMovies()
}
}
}
else
{
cell.data = nil
}

返回单元格
}

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

在这里,我从包装器类加载数据:

  func loadFirstMovies()
{

isLoadingMovies = true

Movies.getMovies({(movieWrapper,error)in
if error!= nil
{
// TODO:改进了错误处理
self.isLoadingMovies = false
let alert = UIAlertController(title: Error,消息:无法加载第一部电影\ (错误?.localizedDescription),preferredStyle:UIAlertControllerStyle.Alert)
alert.addAction(UIAlertAction(标题: Click,样式:UIAlertActionStyle.Default,处理程序:nil))
self.presentViewController(alert ,动画:true,完成:nil)
}
self.addMoviesFromWrapper(movieWrapper)
self.activityIndi​​cator.hidden = true
self.isLo adingMovies = false
self.collectionView.reloadData()
})
}

func loadMoreMovies(){

self.isLoadingMovies =如果self.movi​​es!= nil&&,则为true
self.movi​​eWrapper!=无&& self.movi​​eWrapper!.page< self.movi​​eWrapper!.totalPages
{
// //还有更多种类!
Movies.getMoreMovies(self.movi​​eWrapper,completeHandler:{(moreWrapper,error)in
if error!= nil
{
// TODO:改进了错误处理
self.isLoadingMovies = false
让警报= UIAlertController(标题:错误,消息:无法加载更多电影\(error?.localizedDescription),首选样式:UIAlertControllerStyle.Alert)
警报。 addAction(UIAlertAction(title: Click,style:UIAlertActionStyle.Default,handler:nil))
self.presentViewController(alert,animation:true,complete:nil)
}
print( 更多!)
self.addMoviesFromWrapper(moreWrapper)
self.isLoadingMovies = false
self.collectionView.reloadData()
})
}
}

func addMoviesFromWrapper(wrapper:MovieWrapper?)
{
self.movi​​eWrapper =包装器
如果self.movi​​es ==零
{
self.movi​​es = self.movi​​eWrapper?.results
}
if self.movi​​eWrapper!= nil& self.movi​​eWrapper!.results!=无
{
self.movi​​es = self.movi​​es! + self.movi​​eWrapper !.结果!
}
}

最后我打电话给: viewDidLoad()

中的loadFirstMovies()

编辑:
UpcomingCollectionViewCell

  class UpcomingCollectionViewCell:UICollectionViewCell {

@IBOutlet弱var imageView: UIImageView!


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

func setupData(){

self.imageView.image = nil //如果let urlString = data {
let url = NSURL(string)重置图像

: http://image.tmdb.org/t/p/w342/ + urlString)
self.imageView.hnk_setImageFromURL(url!)


}
}
}


解决方案

典型的表视图/集合视图设置问题。



每次使用诸如 dequeueReusableCellWithReuseIdentifier:之类的出队方法回收单元格时, ,您必须始终完全配置单元格中的所有视图,包括将所有文本字段/图像视图设置为其初始值。您的代码中包含多个if语句,如果if的条件为false,则无需在单元格中设置视图。您需要有else子句,以清除单元格视图中的旧内容,以防上次使用该单元格时剩余内容。



**编辑:



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

  func collectionView(collectionView:UICollectionView,
cellForItemAtIndexPath indexPath:NSIndexPath)-> UICollectionViewCell
{
let cell =
collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier,
forIndexPath:indexPath)as! UpcomingCollectionViewCell
cell.imageView.image = nil; //从回收单元中删除图像
//其余方法...


The problem:

I have a CollectionView which loads a UIimage into each cell. However my problem is that when I load additional cells with more images they appear to duplicate. I can't quite see what could be causing this in my code. Might it be because of some problem with reusable cells?

Can anyone see why this occurs?

NOTE: The array with the images doesn't have duplicates

Video of problem: https://www.youtube.com/watch?v=vjRsFc8DDmI

Image of the problem:

Here are my functions for 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)
}

Here I load the data from a Wrapper class:

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!
    }
}

And lastly I call: loadFirstMovies() in viewDidLoad()

EDIT: The UpcomingCollectionViewCell

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!)


      }
    }  
 }

解决方案

This is a typical table view/collection view setup issue.

Any time you recycle a cell using a dequeue method like dequeueReusableCellWithReuseIdentifier:, you must always fully configure all the views in the cell, including setting all the text fields/image views to their starting values. Your code has several if statements where, if the condition of the if is false, you don't set up the views in the cell. You need to have else clauses that clear out old content from the cell's views in case there is content left over from the last time the cell was used.

**EDIT:

Change your cellForItemAtIndexPath method to begin like this:

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 ...

这篇关于加载更多数据时,CollectionView重复单元格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆