1

Why my custom button in CollectionView load only into last cell?

How can i make that button load in all cells?

var editButton = UIButton()

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

    switch ColorSegment.selectedSegmentIndex {
      case 0:
        cell.CardView.backgroundColor = ColorArray[indexPath.row]
        cell.ColorName.text = ColorName[indexPath.row]
      case 1:
        cell.CardView.backgroundColor = CustomColorArray[indexPath.row]
        cell.ColorName.text = CustomColorName[indexPath.row]

        editButton.frame = CGRect(x:63, y:0, width:20,height:20)
        editButton.layer.cornerRadius = 10
        editButton.backgroundColor = UIColor.lightGray
        editButton.layer.setValue(indexPath.item, forKey: "index")
        editButton.setImage(UIImage(named: "CloseScan"), for: UIControlState.normal)
        editButton.addTarget(self, action: #selector(deleteCell), for: UIControlEvents.touchUpInside)
        cell.addSubview(editButton)
      default: print("error with switch statement for cell data")
    }
    return cell
}

Edit Button Function

     if EditButton.currentTitle == "Edit" {
            EditButton.setTitle("Cancel", for: .normal)
            //DeleteButton.isHidden = false
     } else if EditButton.currentTitle == "Cancel" {
            EditButton.setTitle("Edit", for: .normal)
            //DeleteButton.isHidden = true
     }
1
  • Don't create a instance variable for the button, it must be a local variable in - case 1 Commented Aug 6, 2018 at 6:34

3 Answers 3

2

The problem is you are adding same editButton in all the cell, you need to create new UIButton for all the cell.

So change line

editButton.frame = CGRect(x:63, y:0, width:20,height:20)

With

//Create new button instance every time
let editButton = UIButton(frame: CGRect(x:63, y:0, width:20,height:20))

Also cellForItemAt will reuse the cell so instead of creating new UIButton each time you can try like this.

let editButton: UIButton 
if let btn = cell.viewWithTag(101) as? UIButton {
    editButton = btn
}
else  {
    editButton = UIButton(frame: CGRect(x:63, y:0, width:20,height:20))
}
editButton.layer.cornerRadius = 10
editButton.backgroundColor = UIColor.lightGray
editButton.layer.setValue(indexPath.item, forKey: "index")
editButton.setImage(UIImage(named: "CloseScan"), for: UIControlState.normal)
editButton.addTarget(self, action: #selector(deleteCell), for: UIControlEvents.touchUpInside)
//Set tag for reuse
editButton.tag = 101
cell.addSubview(editButton)

You can get indexPath of cell in button action like this.

@objc func deleteCell(_ sender: UIButton) {
    let point = sender.superview?.convert(sender.center, to: self.collectionView) ?? .zero
    guard let indexPath = self.collectionView.indexPathForItem(at: point) else { return }
    //Use indexPath here
}

Edit: If you want to hide or show the button than its better that you just add button in your design and create one outlet of in your CustomCollectionViewCell after that in cellForItemAt just hide and show button on basis of condition. From your code you need to show the delete button if selected index of segment is 1. So make your cellForItem like this.

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

    cell.CardView.backgroundColor = ColorArray[indexPath.row]
    cell.ColorName.text = ColorName[indexPath.row]
    //Add delete button in the xib or storyboard collectionViewCell
    //Now hide this button if EditButton title is not "Edit"
    cell.editButton.isHidden = EditButton.currentTitle != "Edit"
    //Add action of button
    cell.editButton.addTarget(self, action: #selector(deleteCell), for: UIControlEvents.touchUpInside)
    return cell
}

After that in your edit button action reload the collectionView after you set the button title.

if EditButton.currentTitle == "Edit" {
    EditButton.setTitle("Cancel", for: .normal)
} else if EditButton.currentTitle == "Cancel" {
    EditButton.setTitle("Edit", for: .normal)
}
//Reload your collectionView
self.collectionView.reloadData()
Sign up to request clarification or add additional context in comments.

10 Comments

what you want to do in ViewDidLoad with the button ?
@NiravD Could you help how to hide the button using the tag?
@B2Fq I'm not getting your question to show delete button in all cell you have to create new button object in cellForItem also in which cell you want to hide the cell ? Edit your question with more detail
@NiravD You need to hide in all. I'm doing the on/off editing mode.
@NiravD Am I doing the right thing? let button = self.view.viewWithTag(101) as! UIButton button.isHidden = true
|
1

I think you could move the line:

var editButton = UIButton()

To func cellForItemAt :

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

    switch ColorSegment.selectedSegmentIndex {
      case 0:
        cell.CardView.backgroundColor = ColorArray[indexPath.row]
        cell.ColorName.text = ColorName[indexPath.row]
      case 1:
        cell.CardView.backgroundColor = CustomColorArray[indexPath.row]
        cell.ColorName.text = CustomColorName[indexPath.row]

        // create editButton in here
        var editButton = UIButton()

        editButton.frame = CGRect(x:63, y:0, width:20,height:20)
        editButton.layer.cornerRadius = 10
        editButton.backgroundColor = UIColor.lightGray
        editButton.layer.setValue(indexPath.item, forKey: "index")
        editButton.setImage(UIImage(named: "CloseScan"), for: UIControlState.normal)
        editButton.addTarget(self, action: #selector(deleteCell), for: UIControlEvents.touchUpInside)
        cell.addSubview(editButton)

      default: print("error with switch statement for cell data")
    }
    return cell
}

Comments

1

move your button logic outside of switch statement like this

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

switch ColorSegment.selectedSegmentIndex {
  case 0:
    cell.CardView.backgroundColor = ColorArray[indexPath.row]
    cell.ColorName.text = ColorName[indexPath.row]
  case 1:
    cell.CardView.backgroundColor = CustomColorArray[indexPath.row]
    cell.ColorName.text = CustomColorName[indexPath.row]

  default: print("error with switch statement for cell data")
}
    var editButton = UIButton.init(frame: CGRect.init(x: 63, y: 0, width: 20, height: 20))
    editButton.layer.cornerRadius = 10
    editButton.backgroundColor = UIColor.lightGray
    editButton.layer.setValue(indexPath.item, forKey: "index")
    editButton.setImage(UIImage(named: "CloseScan"), for: UIControlState.normal)
    editButton.addTarget(self, action: #selector(deleteCell), for: UIControlEvents.touchUpInside)
    cell.addSubview(editButton)
return cell

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.