Luis Ramirez
Luis Ramirez

Reputation: 1644

Hiding button inside table view cell

Having problem hiding a button in a UITableViewCell. I am adding a button to my UITableViewCell based if the label.text is bigger than the label container, so if the text is truncated. I'm getting a problem or a bug, the button shows up even when the text is not truncated. This is how the simulator looks like.

enter image description here

So the button still shows when the text isn't truncated. I'm trying to use the console to figure out what is going on. It's weird because the console prints it out correctly, but when I start scrolling somehow it show's the label is truncated. Here is what the console prints out when the app first launches on the left, which is correct. When I start scrolling it prints out the one on the right, where Jackie should be false and not true.

enter image description here

Now I don't know why it is printing out true when it should be false. I'm not sure if this is happening because we reuse UITableViewCell. But this is how my UITableViewCell file looks like. Also the isTruncated is a helper method that I found that helps me check if the label is truncated or not.

class ItemCell: UITableViewCell {

@IBOutlet weak var itemImageView: UIImageView!
@IBOutlet weak var itemTitleLabel: UILabel!
@IBOutlet weak var itemDetailLabel: UILabel!
@IBOutlet weak var moreButton: UIButton!

weak var delegate: ItemCellDelegate?

var item: Item? {
    didSet {

        configureCell()
    }
}

private func configureCell() {

    guard let item = item else { return }

    itemDetailLabel.text = item.description
    itemImageView.image = item.image
    itemTitleLabel.text = item.name

    if itemDetailLabel.isTruncated {
        moreButton.isHidden = false
    }
    else {
        moreButton.isHidden = true
    }

    print("Name: \(item.name)\nisTextTruncated: \(itemDetailLabel.isTruncated)\n")
}

@IBAction func showMoreBtn() {

    delegate?.getSelected(cell: self)
}
}

UITableView cellForRowAt Method

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath) as? ItemCell else {
        return UITableViewCell()
    }

    let item = categories[indexPath.section].items[indexPath.row]


    cell.item = item

    cell.delegate = self

    //Even tried updating the data model
    // categories[indexPath.Section].items[indexPath.row] = item

    return cell
}

Been stuck here for quite a bit trying to figure out what is going on, so I would really really appreciate the help.

Okay here is the isTruncated code. Here is also a link to a video I just posted up, for a better visual of the problem. Video Sample, pay attention to the Jackie cell/row.

extension UILabel {

var isTruncated: Bool {

    guard let labelText = text else {
        return false
    }

    let labelTextSize = (labelText as NSString).boundingRect(
        with: CGSize(width: frame.size.width, height: .greatestFiniteMagnitude),
        options: .usesLineFragmentOrigin,
        attributes: [.font: font],
        context: nil).size

    return labelTextSize.height > bounds.size.height
}
}

Upvotes: 0

Views: 672

Answers (2)

Faysal Ahmed
Faysal Ahmed

Reputation: 7669

I think the problem is getting the value of isTruncated. Try to use this extension for checking text is truncated or not. I think line number checking will be the trick to doing this.

extension UILabel {

    func countLabelLines() -> Int {
        // Call self.layoutIfNeeded() if your view is uses auto layout
        let myText = self.text! as NSString
        let attributes = [NSFontAttributeName : self.font]

        let labelSize = myText.boundingRect(with: CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attributes, context: nil)
        return Int(ceil(CGFloat(labelSize.height) / self.font.lineHeight))
    }

    func isTruncated() -> Bool {

        if (self.countLabelLines() > self.numberOfLines) {
            return true
        }
        return false
    }
} 

Upvotes: 1

Rocker
Rocker

Reputation: 1269

Try below code for creating reusableCell.

let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell") as! ItemCell

as? It will return an optional value and if the downcasting wasn't possible it will return nil and in your case because of guard statement it is returning UITableViewCell

Upvotes: 0

Related Questions