skip to Main Content

I have tried multiple different methods to try and make a method that stops my button from being ticked multiple times at once. In the "selectButton" action, I’m looking for a method that assigns the "checkLabel" UILabel with a checkmark, and for that same tick to disappear when another cell is tapped (e.g. I tap "selectButton" somewhere else).

Here is my tableview cell file:

class NewTableViewCell: UITableViewCell {

    
    var doesContainTick = false
    var count = 1
    
    @IBOutlet var langaugeBox: UIView!
    @IBOutlet var languageText: UILabel!
    @IBOutlet var checkLabel: UILabel?
    
    
    @IBAction func selectButton(_ sender: UIButton) {
        
        if sender.isEnabled {
        
            
            if count == 1 {
                checkLabel?.text = "u{02713}"
                count = 2
            } else {
                checkLabel?.text = ""
            }
         
        }
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
    }
    
}

I tried using different variables in which I would make a counting system (e.g. if "count" is equal to 3, delete tick) which didn’t work (and was deleted multiple times albeit you can sort of see I was trying again above.)

2

Answers


  1. Chosen as BEST ANSWER

    Guys it was so simple how did we all not get it!

    class NewTableViewCell: UITableViewCell {

    var doesContainTick = false
    var count = 1
    
    @IBOutlet var langaugeBox: UIView!
    @IBOutlet var languageText: UILabel!
    @IBOutlet var checkLabel: UILabel?
    
    
    @IBAction func selectButton(_ sender: UIButton) {
        
        if sender.isEnabled {
        
            
            if count == 1 {
                checkLabel?.text = "u{02713}"
                count = 2
            } else {
                checkLabel?.text = ""
            }
         
        }
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
    

    --- Between here:

    if selected {

            checkLabel?.text = "u{02713}" (checkmark)
             } else {
            checkLabel?.text = ""
            
        }
    

    --- and here:

    }
    

    }


  2. It’s helpful to remember two points when building a table view. First, the view controller should be in charge of managing the state for the entire table view; rather than attempting to figure out the state of other cells from within a cell, keep track of the state with the view controller. Second, cells are reused when scrolling, so you cannot depend upon the state of a cell being correct after it is scrolled off screen.

    With this in mind, we want to delegate the handling of the button taps from the cell to the view controller. Create a new delegate protocol, and call the relevant delegate method from your button tap action. Here’s an example of how your cell and its delegate might look:

    protocol NewTableViewCellDelegate: AnyObject {
        func cellButtonTapped(_ cell: NewTableViewCell, at indexPath: IndexPath)
    }
    
    class NewTableViewCell: UITableViewCell {
        weak var delegate: NewTableViewCellDelegate?
    
        @IBOutlet private weak var languageText: UILabel!
        @IBOutlet private weak var checkLabel: UILabel!
        
        var showCheckmark: Bool {
            get {
                self.checkLabel.text == "u{02713}"
            }
            set {
                self.checkLabel.text = newValue ? "u{02713}" : nil
            }
        }
        
        func configure(text: String, showCheckmark: Bool) {
            self.languageText.text = text
            self.showCheckmark = showCheckmark
        }
        
        @IBAction private func buttonTapped(_ sender: UIButton) {
            delegate?.cellButtonTapped(self, at: IndexPath(row: tag, section: 0))
        }
    }
    

    In your view controller add a property that tracks the currently checked cell, and then make your view controller conform to NewTableViewCellDelegate. In the implementation of the cellButtonTapped(_:at:) update the cell’s checkmark, and uncheck the previous cell.

    final class ViewController: UITableViewController, NewTableViewCellDelegate {
        
        private var cellData: [String] = {
            (0..<100).map { "Language ($0)" }
        }()
        
        private var selectedIndexPath: IndexPath?
        
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.register(UINib(nibName: "NewTableViewCell", bundle: nil), 
                               forCellReuseIdentifier: "SelectableCell")
        }
    
        override func tableView(_ tableView: UITableView, 
                                numberOfRowsInSection section: Int) -> Int {
            return cellData.count
        }
        
        override func tableView(_ tableView: UITableView, 
                                cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(
                withIdentifier: "SelectableCell",
                for: indexPath
            ) as! NewTableViewCell
            
            if cell.delegate == nil {
                cell.delegate = self
            }
            
            let text = cellData[indexPath.row]
            //If the cell is selected, show checkmark. This is important in case the
            //cell was off screen when it's checkbox state changed.
            cell.configure(text: text, showCheckmark: selectedIndexPath == indexPath)
            cell.tag = indexPath.row //Use the tag to track the row.
            
            return cell
        }
        
        func cellButtonTapped(_ cell: NewTableViewCell, at indexPath: IndexPath) {
            cell.showCheckmark = true
            
            if let i = selectedIndexPath,
               let previousCell = tableView.cellForRow(at: i) as? NewTableViewCell {
                previousCell.showCheckmark = false
            }
            
            selectedIndexPath = indexPath
        }
        
    }
    

    Alternatively, rather than adding a button to your cell and creating a custom delegate protocol, you can simply implement the UITableViewDelegate.tableView(_:didSelectRowAt:) method to update the cells when one is tapped.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search