加载更多数据时 CollectionView 重复单元格
CollectionView duplicate cell when loading more data
问题:
我有一个 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)
}
这里我从包装器加载数据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!
}
}
最后我在 viewDidLoad()
中调用:loadFirstMovies()
编辑:
即将推出的 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!)
}
}
}
这是典型的 table view/collection 视图设置问题。
任何时候使用像 dequeueReusableCellWithReuseIdentifier:
这样的出列方法回收单元格时,您必须始终完全配置单元格中的所有视图,包括将所有文本 fields/image 视图设置为它们的起始值。您的代码有几个 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 ...
在您的自定义单元格 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!)
}
}
问题:
我有一个 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)
}
这里我从包装器加载数据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!
}
}
最后我在 viewDidLoad()
loadFirstMovies()
编辑: 即将推出的 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!)
}
}
}
这是典型的 table view/collection 视图设置问题。
任何时候使用像 dequeueReusableCellWithReuseIdentifier:
这样的出列方法回收单元格时,您必须始终完全配置单元格中的所有视图,包括将所有文本 fields/image 视图设置为它们的起始值。您的代码有几个 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 ...
在您的自定义单元格 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!)
}
}