Reputation: 1644
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.
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.
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
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
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