As you can see in this image
the UITextView changes it's height according to the text length, I want to make it adjust it's height according to the text length.
*I saw other questions, but solutions there didn't work for me
As you can see in this image
the UITextView changes it's height according to the text length, I want to make it adjust it's height according to the text length.
*I saw other questions, but solutions there didn't work for me
 
    
    this Works for me, all other solutions didn't.
func adjustUITextViewHeight(arg : UITextView) {
    arg.translatesAutoresizingMaskIntoConstraints = true
    arg.sizeToFit()
    arg.scrollEnabled = false
}
In Swift 4 the syntax of arg.scrollEnabled = false has changed to arg.isScrollEnabled = false.
 
    
    In Storyboard / Interface Builder simply disable scrolling in the Attribute inspector.
In code textField.scrollEnabled = false should do the trick.
 
    
     
    
    All I had to do was:
This allows autolayout to dynamically size the textView based on its content.
 
    
    Give this a try:
CGRect frame = self.textView.frame;
frame.size.height = self.textView.contentSize.height;
self.textView.frame = frame;
Edit- Here's the Swift:
var frame = self.textView.frame
frame.size.height = self.textView.contentSize.height
self.textView.frame = frame
 
    
    Swift 4
Add It To Your Class
UITextViewDelegate
func textViewDidChange(_ textView: UITextView) {
      let fixedWidth = textView.frame.size.width
      textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
      let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
      var newFrame = textView.frame
      newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
      textView.frame = newFrame
}
 
    
    Followed by DeyaEldeen's answer. 
In my case. I grow the textview height automatically by adding 
swift 3 
textView.translatesAutoresizingMaskIntoConstraints = false
 textView.isScrollEnabled = false
 
    
    Swift 5, Use extension:
extension UITextView {
    func adjustUITextViewHeight() {
        self.translatesAutoresizingMaskIntoConstraints = true
        self.sizeToFit()
        self.isScrollEnabled = false
    }
}
Usecase:
textView.adjustUITextViewHeight()
And don't care about the height of texeView in the storyboard (just use a constant at first)
 
    
    just make a connection with your textView's height Constraint
@IBOutlet var textView: UITextView!
@IBOutlet var textViewHeightConstraint: NSLayoutConstraint!
and use this code below
textViewHeightConstraint.constant = self.textView.contentSize.height
 
    
    If your textView is allowed to grow as tall as the content, then
textView.isScrollEnabled = false
should just work with autolayout.
If you want to remain the textView to be scrollable, you need to add an optional height constraint,
internal lazy var textViewHeightConstraint: NSLayoutConstraint = {
  let constraint = self.textView.heightAnchor.constraint(equalToConstant: 0)
  constraint.priority = .defaultHigh
  return constraint
}()
public override func layoutSubviews() {
  super.layoutSubviews()
  // Assuming there is width constraint setup on the textView.
  let targetSize = CGSize(width: textView.frame.width, height: CGFloat(MAXFLOAT))
  textViewHeightConstraint.constant = textView.sizeThatFits(targetSize).height
}
The reason to override layoutSubviews() is to make sure the textView is laid out properly horizontally so we can rely on the width to calculate the height.
Since the height constraint is set to a lower priority, if it runs out space vertically the actual height of the textView will be less than the contentSize. And the textView will be scrollable.
 
    
    I added these two lines of code and work fine for me.
Works in Swift 5+
func adjustUITextViewHeight(textView : UITextView)
{
     textView.translatesAutoresizingMaskIntoConstraints = true
     textView.isScrollEnabled = false
     textView.sizeToFit()
}
This answer may be late but I hope it helps someone.
For me, these 2 lines of code worked:
textView.isScrollEnabled = false
textView.sizeToFit()
But don't set height constraint for your Textview
 
    
    it's straight forward to do in programatic way. just follow these steps
add an observer to content length of textfield
[yourTextViewObject addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
implement observer
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
UITextView *tv = object;
    //Center vertical alignment
    CGFloat topCorrect = ([tv bounds].size.height - [tv contentSize].height * [tv zoomScale])/2.0;
    topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
    tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
    mTextViewHeightConstraint.constant = tv.contentSize.height;
    [UIView animateWithDuration:0.2 animations:^{
        [self.view layoutIfNeeded];
    }];
}
if you want to stop textviewHeight to increase after some time during typing then implement this and set textview delegate to self.
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
    if(range.length + range.location > textView.text.length)
    {
        return NO;
    }
    NSUInteger newLength = [textView.text length] + [text length] - range.length;
    return (newLength > 100) ? NO : YES;
}
 
    
    Swift 4+
This is extremely easy with autolayout! I'll explain the most simple use case. Let's say there is only a UITextView in your UITableViewCell.
textView to the contentView with constraints.textView.tableView on textViewDidChange.That's all!
protocol TextViewUpdateProtocol {
    func textViewChanged()
}
class TextViewCell: UITableViewCell {
    
    //MARK: Reuse ID
    static let identifier = debugDescription()
    
    //MARK: UI Element(s)
    /// Reference of the parent table view so that it can be updated
    var textViewUpdateDelegate: TextViewUpdateProtocol!
    
    lazy var textView: UITextView = {
        let textView = UITextView()
        textView.isScrollEnabled = false
        textView.delegate = self
        textView.layer.borderColor = UIColor.lightGray.cgColor
        textView.layer.borderWidth = 1
        textView.translatesAutoresizingMaskIntoConstraints = false
        return textView
    }()
    
    //MARK: Padding Variable(s)
    let padding: CGFloat = 50
    
    //MARK: Initializer(s)
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        addSubviews()
        addConstraints()
        
        textView.becomeFirstResponder()
    }
    
    //MARK: Helper Method(s)
    func addSubviews() {
        contentView.addSubview(textView)
    }
    
    func addConstraints() {
        textView.leadingAnchor  .constraint(equalTo: contentView.leadingAnchor, constant: padding).isActive = true
        textView.trailingAnchor .constraint(equalTo: contentView.trailingAnchor, constant: -padding).isActive = true
        textView.topAnchor      .constraint(equalTo: contentView.topAnchor, constant: padding).isActive = true
        textView.bottomAnchor   .constraint(equalTo: contentView.bottomAnchor, constant: -padding).isActive = true
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}
extension TextViewCell: UITextViewDelegate {
    
    func textViewDidChange(_ textView: UITextView) {
        textViewUpdateDelegate.textViewChanged()
    }
    
}
Now you have to inherit implement the protocol in your ViewController.
extension ViewController: TextViewUpdateProtocol {
    
    func textViewChanged() {
        tableView.beginUpdates()
        tableView.endUpdates()
    }
    
}
Check out my repo for the full implementation.
 
    
    SWIFT 4
Change the size when typing
UITextViewDelegate
func textViewDidChange(_ textView: UITextView) {
        yourTextView.translatesAutoresizingMaskIntoConstraints = true
        yourTextView.sizeToFit()
        yourTextView.isScrollEnabled = false
        let calHeight = yourTextView.frame.size.height
        yourTextView.frame = CGRect(x: 16, y: 193, width: self.view.frame.size.width - 32, height: calHeight)
    }
Change the size when load
func textViewNotasChange(arg : UITextView) {
        arg.translatesAutoresizingMaskIntoConstraints = true
        arg.sizeToFit()
        arg.isScrollEnabled = false
        let calHeight = arg.frame.size.height
        arg.frame = CGRect(x: 16, y: 40, width: self.view.frame.size.width - 32, height: calHeight)
    }
Call the function of the second option like this:
textViewNotasChange(arg: yourTextView)
 
    
     
    
    In my project, the view controller is involved with lots of Constraints and StackView, and I set the TextView height as a constraint, and it varies based on the textView.contentSize.height value.
step1: get a IB outlet
@IBOutlet weak var textViewHeight: NSLayoutConstraint!
step2: use the delegation method below.
extension NewPostViewController: UITextViewDelegate {
     func textViewDidChange(_ textView: UITextView) {
          textViewHeight.constant = self.textView.contentSize.height + 10
     }
}
 
    
     
    
    Better yet swift 4 add as an extension:
extension UITextView {
    func resizeForHeight(){
        self.translatesAutoresizingMaskIntoConstraints = true
        self.sizeToFit()
        self.isScrollEnabled = false
    }
}
 
    
    its working
func textViewDidChange(_ textView: UITextView) {
    let fixedWidth = textviewconclusion.frame.size.width
    textviewconclusion.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    let newSize = textviewconclusion.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    var newFrame = textviewconclusion.frame
    newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
    textviewconclusion.frame = newFrame
}
 
    
    1 Add an observer to the content length of textfield
   yourTextView.addObserver(self, forKeyPath: "contentSize", options: (NSKeyValueObservingOptions.new), context: nil);
2 Implement observer
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        let tv = object as! UITextView;
        var topCorrect = (tv.bounds.size.height - tv.contentSize.height * tv.zoomScale)/2.0;
        topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
        tv.contentOffset.x = 0;
        tv.contentOffset.y = -topCorrect;
        self.yourTextView.contentSize.height = tv.contentSize.height;
        UIView.animate(withDuration: 0.2, animations: {
            self.view.layoutIfNeeded();
        });
    }
 
    
    Here are two pitfalls in iOS 8.3 when coming with textView.textContainer.maximumNumberOfLines = 10
Refer to my gist, please.
textView.attributedText = originalContent
let lineLimit = 10
textView.isEditable = true
textView.isScrollEnabled = false
textView.textContainerInset = .zero // default is (8, 0, 8, 0)
textView.textContainer.maximumNumberOfLines = lineLimit // Important condition
textView.textContainer.lineBreakMode = .byTruncatingTail
// two incomplete methods, which do NOT work in iOS 8.3
// size.width可能比maxSize.width小 ————遗憾的是 iOS 8.3 上此方法无视maximumNumberOfLines参数,所以得借助于UILabel
// size.width may be less than maxSize.width, ---- Do NOT work in iOS 8.3, which disregards textView.textContainer.maximumNumberOfLines
// let size = textView.sizeThatFits(maxSize) 
// 遗憾的是 iOS 8.3 上此方法失效了,得借助于UILabel
// Does not work in iOS 8.3
// let size = textView.layoutManager.usedRectForTextContainer(textView.textContainer).size 
// Suggested method: use a temperary label to get its size
let label = UILabel(); label.attributedText = originalContent
let size = label.textRect(forBounds: CGRect(origin: .zero, size: maxSize), limitedToNumberOfLines: lineLimit).size
textView.frame.size = size
 
    
    Declaration here
    fileprivate weak var textView: UITextView!
Call your setupview here
    override func viewDidLoad() {
        super.viewDidLoad()
         setupViews()
    }
Setup here
    fileprivate func setupViews() {
    let textView = UITextView()
    textView.translatesAutoresizingMaskIntoConstraints = false
    textView.text = "your text here"
    textView.font = UIFont.poppinsMedium(size: 14)
    textView.textColor = UIColor.brownishGrey
    textView.textAlignment = .left
    textView.isEditable = false
    textView.isScrollEnabled = false
    textView.textContainerInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
   self.view.addSubview(textView)
   self.textView = textView
   setupConstraints()
   }
Setup constraints here
   fileprivate func setupConstraints() {
    NSLayoutConstraint.activate([
        textView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
        textView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20),
        textView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20),
        textView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20),
        textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 150),
        ])
  }
 
    
    Whenever you need to resize the textview according to the inside content size, like in messageing app. Use cocoapods(GrowingTextView), it will make your life easier, than coding the dynamic resizing of textview on your own.
 
    
     
    
    if you want preload textView on controller load. Call this function from view didload():
func textViewDidChange(_ textView: UITextView) {   
    let esmitated = CGSize(width: txtView.frame.width, height: .infinity)
    let esmitatedSize = txtView.sizeThatFits(esmitated)
    self.heghtConstraint.constant = esmitatedSize.height
}
