Olivia Watkins
Olivia Watkins

Reputation: 526

Swift UICollectionView Cells Mysteriously Repeat

We are trying to make a collection view. In each cell the users can choose an image and enter text into a text field. We noticed that after adding four cells, when we add a new cell, the text field is already filled with the information from previous cells. In our code, we never programmatically fill the text field (which starts out empty), we allow the user to do this. Any suggestions?

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

    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Image", forIndexPath: indexPath) as! CollectionViewCell
    cell.deleteButton?.addTarget(self, action: #selector(AddNewItem.xButtonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside)
    cell.deleteButton?.layer.setValue(indexPath.row, forKey: "index")
    let item = items[indexPath.item]
    let path = getDocumentsDirectory().stringByAppendingPathComponent(item.image)
    cell.imageView.image = UIImage(contentsOfFile: path)
    cell.imageView.layer.borderColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.3).CGColor
    cell.imageView.layer.borderWidth = 2
    cell.layer.cornerRadius = 7

    return cell
}

Upvotes: 2

Views: 2661

Answers (4)

Osama Remlawi
Osama Remlawi

Reputation: 2990

The reason is that collectionViewLayout.collectionViewContentSize.height

is taller than the real contents size! It is recommended to keep UICollectionView calculate the height automatically (without using UIScrollView, let UICollectionView maintain the scroll), as manual change will cause lots of weird behaviors.

Upvotes: 0

Phani Bob
Phani Bob

Reputation: 795

You can use this in UICollectionViewCell custom class

override func prepareForReuse() {
    self.profileImg.image = #imageLiteral(resourceName: "Profile Icon Empty")

    super.prepareForReuse()
}

Upvotes: 5

Olivia Watkins
Olivia Watkins

Reputation: 526

Here's how I ultimately ended up resolving it.

I created an Item class which contained all of the fields which are shown in the collection view cell and created an array of Items.

Here is a simplified version of my CollectionViewCell class, which here only has a single text field:

class CollectionViewCell: UICollectionViewCell {

    @IBOutlet weak var itemName: UITextField!

    var item: Item?

    func initializeListeners(){
        itemName.addTarget(self, action: #selector(itemNameChanged(_:)), forControlEvents: UIControlEvents.EditingChanged)
    }


    //When the item name is changed, make sure the item's info is updated
    func itemNameChanged(textField: UITextField) {
        item?.itemName = textField.text!
    }
}

Here's a simplified version of the cellForItemAtIndexPath function in my view controller class:

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionViewCell
    cell.initializeListeners()
    let item = items[indexPath.item]
    cell.item = item
    cell.itemName.text = item.itemName
    return cell
}

Upvotes: 0

Volodymyr
Volodymyr

Reputation: 1205

Problem is that you are using dequeReusableCellWithIdentifier which returns already created cell(that you were using before). That's why it's already filled with previous data. You need to clear this data before showing this cell, or fill it from some storage(for example array that represents your collection view cells(each object in array somehow related to cell, in your case that is text wroten in cell))

Upvotes: 3

Related Questions