Embedding UITextView in UITableViewCell
May there be the proper height ~~~
Have you ever try to put a UITextView inside a UITableViewCell and hope that the cell will self-adjust while typing in UITextView? Well, look no further.
Before I get started, I would like to thank you for the people who have shared their code selflessly. I have shared their reference at the bottom. Feel free to take a look.
In this exercise, We’ll be using static cells. For dynamic, please check on the reference links.
For people who just want to test the project first, just click on the link below:
Let’s Get Started :


We will first create a Single View App and replace the ViewController in Main.storyboard with a Table View Controller.


Now, change the the super class used in ViewController.swift to UITableViewController and set the class of the Table View Controller in the storyboard to viewController .
UI Setup :
We will now place UITextView into different cells and setup the constraints as follows:
PS: I left an empty space in the first cell so you can see the code in effect, when the keyboard is shown.


Finally, remember to connect these UITextView to ViewController.swift as @IBOutlets. Oh and also remember to set the TableView’s content as Static Cells, otherwise you will get an error saying that you cannot connect the IBOutlets to repeating content (something similar)

Coding Time :
Believe it or not, here comes the easy part.
What you need to do right now is the set the ViewController as the delegate of UITextViewDelegate and do some basic setup to the TextViews :

At viewDidLoad, we will make sure all the textViews’ delegate is pointed to the viewController.swift. However, we are also going to set whether they are scrollable as shown above, this is so that you can see the different response in the UI.
Next, let’s setup the keyboard for textViews, since UITextView can be multiline, so unlike UITextField where you can detect the return button pressed and resign the textField when the UITextFieldDelegate “textField: shouldReturn” is called.


The code above will setup the keyboard for each of the textViews with a Done button at the top, which will resign all the textViews from the First Responder.
Finally, let’s deal with the UITextViewDelegate.
The delegate method that we are interested in is :
func textViewDidChange(_ textView: UITextView)Since we have set up the constraints in the storyboard, we can ask the tableView to update and let the auto-layout to do the work.
Therefore, we will ask the tableView to update whenever textView.text has changed:
func textViewDidChange(_ textView: UITextView) {
tableView.beginUpdates()
tableView.endUpdates()
}Let’s take a look what will happen:
Trail #1

As you see, when the tableView updates, the cells will be animated to show the proper bounds. In order to stop that from happening, we will add a single lined code right after the previous code :
UIView.setAnimationsEnabled(false)Also, please note that the textViews in Row #1 and Row #2 are not shown. The reason is that they are both scrollable, meaning their height can be as small as 0. We can see this using “Debug View Hierarchy”.

Trail #2

Now things are getting better. However, we want the bottom of the cell to be shown instead of hiding behind the keyboard.
So we are going to tell the tableView to scroll to the indexPath of interest :

Trail #3

If this is what you wish to achieve, then you are ready. You are very welcome ^^.
THE END
Reference :
Tools used :
|
|
|
|
AFTER CREDIT CODE
|
|
|
|
|
For people who went as far as here, you must be full of curiosity . So let me repay you by a bonus round.
I am not sure about you, but I am not at all satisfied with the result. I don’t want my textView to go infinitely long (height). What I want is the textView to have a limited height. So how do we do that?
Bonus Round
First, let take the last textView as an example. In the textViewDelegate, we will make the textView_5 scrollable when its frame.height ≥ 200.

Trial #4

As you can see, everything seems fine at first. But once the cell disappeared, and redrawn when appeared, it became just like textView_1 and textView_2. By setting textView_5 to be scrollable, it will be squished by the tableViewCell and it can’t be seen no more.
So what can we do? Well, the easy version is simply override :
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloatSince we only want to make sure textView_5 does not squished by the cell, we will simply return the limited height we want for cell containing textView_5 and the rest will return the default height.

The reason I am taking into account of the minY is because I am not trying to constraint the top and bottom of textView_5 to the top and bottom of the cell. Instead, in the storyboard we constraint textView_5 top and bottom to the marginGuide of the top and bottom of the cell.
Finally, here is what we get :

Ha ~ that was easy wan’t it?
Please clap if you find this tutorial useful. THANK YOU.