I have a UILabel in a cell of UITableView.
To adjust the height of the cell depending the height of the label, it's ok, it works perfectly.
But I need to add another constraints. I need to display the UILabel with a typewriter effect (letter by letter).
My extension for the effect works well:
extension UILabel{
    func setTextWithTypeAnimation(id:String, typedText: String, pauseCharacterArray: [Int:Double], characterInterval: TimeInterval = 0.06 ) {
        text = ""
        let group = DispatchGroup()
        group.enter()
        DispatchQueue.global(qos: .userInteractive).async {
            for (index, character) in typedText.characters.enumerated() {
                DispatchQueue.main.async {
                    self.text = self.text! + String(character)
                }
                Thread.sleep(forTimeInterval: characterInterval)
            }
        group.leave()
    }
    group.notify(queue: .main) {
        //do something
    }
}
I tried to call this function in my configureCell fund :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ParagraphTableViewCell", for: indexPath) as! ParagraphTableViewCell
    cell.delegate = self
    self.configureCell(cell: cell, atIndexPath: indexPath)
    return cell
 }
func configureCell(cell: ParagraphTableViewCell, atIndexPath indexPath: IndexPath) {
    let paragraph = paragraphArray[indexPath.row] as! Paragraph
    let pauseCharactersArray:[Int:Double] = [1:0, 6:0]
    cell.dialogueLabel.setTextWithTypeAnimation(id:"intro", typedText: "lorem ipsum", pauseCharacterArray: pauseCharactersArray)
}
But the label doesn't appear. I think it's because the height of the label in the cell is set to 0, and it's never updated.
I don't know how to adjust the height of the cell "in live" (every time a character is displayed)
EDIT
I use autolayout
EDIT 2
The typewriter effect, run in a simple UILabel without UITableView:

The cell set in the xib:

When I run, the UILabel doesn't appear:

I was able to achieve using a different method.
Here is my IB Screen Shot to use as reference.
On your ViewController, set the following properties:
yourTableView.rowHeight = UITableViewAutomaticDimension
yourTableView.rowHeight.estimatedRowHeight = 40 // You should set an initial estimated row height here, the number 40 was chosen arbitrarily
I edited your method to add an callback.
func setTextWithTypeAnimation(id:String, typedText: String, pauseCharacterArray: [Int:Double], characterInterval: TimeInterval = 0.06, callBackAfterCharacterInsertion:(()->())?) {
  text = ""
  let group = DispatchGroup()
  group.enter()
  DispatchQueue.global(qos: .userInteractive).async {
    for (_, character) in typedText.characters.enumerated() {
        DispatchQueue.main.async {
            self.text = self.text! + String(character)
            callBackAfterCharacterInsertion?()
        }
        Thread.sleep(forTimeInterval: characterInterval)
    }
    group.leave()
  }
  group.notify(queue: .main) {
    //do something
  }
}
And through the callback, I called the beginUpdates() and endUpdates(), from the TableView, after each character update.
Hope this help you in any way.
I found a solution but I don't know if it's a very clean one.
I added layoutIfNeeded() in configureCell method :
func configureCell(cell: ParagraphTableViewCell, atIndexPath indexPath: IndexPath) {
    let paragraph = paragraphArray[indexPath.row] as! Paragraph
    cell.layoutIfNeeded() 
    let pauseCharactersArray:[Int:Double] = [1:0, 6:0]
    cell.dialogueLabel.setTextWithTypeAnimation(id:"intro", typedText: "lorem ipsum", pauseCharacterArray: pauseCharactersArray)
}
And I added the heightForRowAtIndexPath method in my controller, which returns the height of my label:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let cell = tableView.dequeueReusableCell(withIdentifier: "ParagraphTableViewCell") as! ParagraphTableViewCell
    return cell.dialogueLabel.frame.height
}
It works, but I don't understand exactly why, because in heightForRowAtIndexPath I'm returning the height of the label and not the height of the cell.
If someone has a better solution, I'm interested.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With