0

I have a data like dynamic string.
And I want to check this string is out of my label width which numberOfLines equal one.
If out of my label width, I use cellA.
If not out of my label width, I use cellB.
And my point is how to check and change "isLongName" boolvalue. Have any suggestion to me?

var isLongName: Bool = false

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        // How to check the string is long name (width out of cellB)

        if isLongName && indexPath.row == 3 {                

            let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCellA", for: indexPath) as! TableViewCellA

            cell.titleLabel.text = itemsArray[indexPath.row].title
            cell.subtitleLabel.text = itemsArray[indexPath.row].value
            cell.expandBtn.addTarget(self, action: #selector(expandBtnPressed), for: .touchUpInside)
            cell.expandBtn.tag = indexPath.row

            if isExpand {
                cell.expandBtn.setTitle("close", for: .normal)
                cell.subtitleLabel.numberOfLines = 0
            } else {
                cell.expandBtn.setTitle("open", for: .normal)
                cell.subtitleLabel.numberOfLines = 1
            }

            cell.remakeLayout(isExpand: isExpand)

            return cell

        } else {

            let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCellB", for: indexPath) as! TableViewCellB
            cell.titleLabel.text = itemsArray[indexPath.row].title
            cell.subtitleLabel.text = itemsArray[indexPath.row].value

            return cell
        }

    }

@objc func expandBtnPressed(sender: UIButton) {

        let indexPath = IndexPath(row: sender.tag, section: 0)

        UIView.performWithoutAnimation {
            tableView.beginUpdates()
            self.isExpand = !isExpand
            tableView.reloadRows(at: [indexPath], with: .none)
            tableView.endUpdates()
        }
    }
Beginnerrrrrr
  • 537
  • 1
  • 8
  • 27
  • Please refer to https://stackoverflow.com/questions/3077109/how-to-check-if-uilabel-is-truncated. Hope this will solve your problem – Let's_Create Jun 14 '19 at 06:23
  • @Let's_Create I know this, but how to init cellB to get it's label. And my point is how to check and change "isLongName" boolvalue. – Beginnerrrrrr Jun 14 '19 at 06:26
  • Ok, I understand your problem seems pretty abstract because you are creating a cell and if the label has a large text you want another cell (can't we update the cell A) Can you attach a screenshot of what you are trying to achieve? – Let's_Create Jun 14 '19 at 06:30
  • 1
    I guess you should change the cell A only when the text in the UILabel is to be shown completely. – BhargavR Jun 14 '19 at 06:33

2 Answers2

0

Add following Extension of UILabel

extension UILabel {
    func calculateMaxLines() -> Int {
        let maxSize = CGSize(width: frame.size.width, height: CGFloat(Float.infinity))
        let charSize = font.lineHeight
        let text = (self.text ?? "") as NSString
        let textSize = text.boundingRect(with: maxSize, options: .usesLineFragmentOrigin, attributes: [NSAttributedString.Key.font: font], context: nil)
        let linesRoundedUp = Int(ceil(textSize.height/charSize)) 
        return linesRoundedUp
    }    
}

After assigning text to UIlabel check required a number of lines. if you got a result 1 from calculateMaxLines then not required to show more button.

cell.subtitleLabel.text = itemsArray[indexPath.row].value
print("number of line required: ",cell.subtitleLabel.calculateMaxLines())
AtulParmar
  • 4,358
  • 1
  • 24
  • 45
0

You can use label extension to identify number lines on the label and you can switch cells. Try this extension to identify the number of lines.

extension UILabel {

    func numberOfLines() -> Int {
        let textSize = CGSize(width: self.frame.size.width, height: CGFloat(Float.infinity))
        let rHeight = lroundf(Float(self.sizeThatFits(textSize).height))
        let charSize = lroundf(Float(self.font.lineHeight))
        let lineCount = rHeight/charSize
        return lineCount
    }

}

For your scenario, you could use like this:-

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

       let baseCell = tableView.dequeueReusableCell(withIdentifier: "TableViewCellB", for: indexPath) as! TableViewCellB


        if baseCell.titleLabel.numberOfLines() > 1 && indexPath.row == 3 {                

            let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCellA", for: indexPath) as! TableViewCellA

            cell.titleLabel.text = itemsArray[indexPath.row].title
            cell.subtitleLabel.text = itemsArray[indexPath.row].value
            cell.expandBtn.addTarget(self, action: #selector(expandBtnPressed), for: .touchUpInside)
            cell.expandBtn.tag = indexPath.row

            if isExpand {
                cell.expandBtn.setTitle("close", for: .normal)
                cell.subtitleLabel.numberOfLines = 0
            } else {
                cell.expandBtn.setTitle("open", for: .normal)
                cell.subtitleLabel.numberOfLines = 1
            }

            cell.remakeLayout(isExpand: isExpand)

            return cell

        } else {

            let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCellB", for: indexPath) as! TableViewCellB
            cell.titleLabel.text = itemsArray[indexPath.row].title
            cell.subtitleLabel.text = itemsArray[indexPath.row].value

            return cell
        }

    }
Mudith Chathuranga Silva
  • 7,253
  • 2
  • 50
  • 58