Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting UITextView frame to content size no longer works in Xcode 5

The code snippet below worked to resize a UITextView frame to it's content height, before installing Xcode 5 but it doesn't work since the upgrade:

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

I've searched and haven't found the fix. Any thoughts?

like image 259
Silverstar Avatar asked Sep 17 '13 20:09

Silverstar


4 Answers

There's new stuff for this on iOS 7.

To get the "fitted" size used by the text view after it's updated its text, call usedRectForTextContainer: on the textView's layoutManager property, passing the textView's textContainer property as an argument.

Word of warning about scrolling: Be advised, though, that changing the frame size of a text view after it has updated it's text can have unexpected visual bugs if scrolling is disabled on your text view. If this happens, set scrolling enabled before editing the text of the text view, then disabling it after it's updated (if you need scrolling to remain disabled).

like image 51
jaredsinclair Avatar answered Oct 13 '22 20:10

jaredsinclair


To work in iOS 7 (Xcode 5), just:

  1. Give the entire space to receive the text, by setting:

    [myTextView setScrollEnabled:YES];

  2. Pass the real text:

    myTextView.text = theTextVariable; or myTextView.text = @"The text...";

  3. Autoresize textView:

    [myTextView sizeToFit];

  4. Disable scroll:

    [myTextView setScrollEnabled:NO];

P.S: myTextView can be use also as self.myTextView or _myTextView

And have fun!

like image 31
Matheus Abreu Avatar answered Oct 13 '22 19:10

Matheus Abreu


I believe the correct way to force a textView to update its contentSize is by calling

[textView layoutIfNeeded]

However, in iOS 7.0 and 7.1 this seems still not to work reliably unless you first set

textView.layoutManager.allowsNonContiguousLayout = false;

It's not clear to me whether this is a bug or not since I can't really find a good explanation of what "non-contiguous layout" even means.

(My personal use case is updating textView.text = newValue programmatically, then trying to resize the textView appropriately.)

like image 6
c roald Avatar answered Oct 13 '22 21:10

c roald


[textView sizeToFit];

Is what you need.

All you need to do is make sure that:

[textView setScrollEnabled:YES];

BEFORE you set the UITextView text content.

You can then:

[textView sizeToFit];
[textView setScrollEnabled:NO];

After you've set the text. Same as writing your own bling function or employing complicated bounding rect methods. Why use something so complicated when the solution is as simple as three lines?

That said, wrap those functions like so:

- (void) setText:(NSString *)theTextToAdd andResizeTheDamnTextView:(UITextView *)textView {
    [textView setScrollEnabled:YES];
    [textView setText:theTextToAdd];
    [textView sizeToFit];
    [textView setScrollEnabled:NO];
}

And define it in a per-file or global basis to avoid having to manually write or copy/paste the four lines and call it every time. Just call it as:

[yourTextViewIvar setText:@"DUMMY STRING" andResizeTheDamnTextView:yourTextViewIvar];

If that doesn't work:

[yourTextViewIvar setText:[self setText:@"DUMMY STRING" andResizeTheDamnTextView:yourTextViewIvar]];

And you'll be golden.

I think..

That's Pseudocode. Just FYI.

like image 3
topLayoutGuide Avatar answered Oct 13 '22 19:10

topLayoutGuide