UITextView wraps text when built with iOS 7 SDK

I have a UITextView inside a UIScrollView that worked perfectly fine on iOS 6 built from xcode 4.x, however now building with xcode 5 it doesn’t work properly, even on iOS 6.

The problem is the text wraps with the screen width even though the UITextView and UIScrollView have large widths. I use this code to work out the new width and height of the UITextView, and even though the textview scrolls left/right the text is wrapped as if the width is only the width of the screen.

  • NSPredicate for exact match
  • UIViewController do not rotate to landscape
  • How to add a magnifier to custom control?
  • Rotate image in UIImageView
  • Using OpenSSL cocoa pod in iOS project
  • How to distribute Swift Library without exposing the source code?
  • Thanks

    self.responceTextView.text = [NSString stringWithFormat:@"%@%@",_responceTextView.text,responce];
    [self textViewDidChange:self.responceTextView];
    
    - (void)textViewDidChange:(UITextView *)textView
    {
        // Recalculate size of text field
        CGSize maxSize = CGSizeMake(MAXFLOAT, MAXFLOAT);
        CGSize reqSize = [textView.text sizeWithFont:[UIFont fontWithName:@"Courier" size:12] constrainedToSize:maxSize lineBreakMode:NSLineBreakByClipping];
    
        self.responceTextView.frame = CGRectMake(0, 0, reqSize.width+16, reqSize.height+16);
    
        // Resize scroll view if needs to be smaller so text stays at top of screen
        CGFloat maxScrollHeight = maxScrollViewSize.size.height;
        if (self.responceTextView.frame.size.height < maxScrollHeight) {
            self.responceScrollView.frame = CGRectMake(self.responceScrollView.frame.origin.x, self.responceScrollView.frame.origin.y, self.responceScrollView.frame.size.width, self.responceTextView.frame.size.height);
        } else {
            self.responceScrollView.frame = maxScrollViewSize;
        }
    
        // Set content size
        self.responceScrollView.contentSize = CGSizeMake(self.responceTextView.frame.size.width, self.responceTextView.frame.size.height);
    
        [self scrollToCursor];
    }
    

    EDIT —-

    Ok, so it seems sizeWithFont is deprecated in iOS 7. Strange how I get no compiler warning.
    It still doesn’t make sense that it doesn’t work on iOS 6 (or is it completely removed when built with iOS 7 SDK?)

    I have tried these 2 alternatives, but get exactly the same size back from all.

    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [UIFont fontWithName:@"Courier" size:12], NSFontAttributeName,
                                    nil];
    CGRect rect = [textView.text boundingRectWithSize:maxSize options:NSLineBreakByClipping | NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:attributes context:nil];
    

    returns: {{0, 0}, {439.27148, 168}}

    CGSize rect2 = [textView.text sizeWithAttributes:attributes];
    

    returns: {439.27148, 168}

    And the original above returns {439.27148, 168}

    They should all return a wider view.

    EDIT 2 —-
    It seems from above that the returned frame is correct (439 wide) however it’s the text that is still being word wrapped inside the textview.

    4 Solutions Collect From Internet About “UITextView wraps text when built with iOS 7 SDK”

    try using:

    [textView.text boundingRectWithSize:CGSizeMake(txtFrame.size.width, CGFLOAT_MAX)
                               options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                               attributes:[NSDictionary dictionaryWithObjectsAndKeys:textView.font,NSFontAttributeName, nil] context:nil];
    

    The string measuring seems pretty buggy. This is the only option combination that gives the right size, for the testing I have done.

    I’m using the following code with success in iOS7 (it’s a UITextField with a minimum and maximum height. When the text’s height get larger then MAX_HEIGHT_MESSAGE_TEXTBOX, scrollbars appears in the UITextField).

    const float MAX_HEIGHT_MESSAGE_TEXTBOX = 80;
    const float MIN_HEIGHT_MESSAGE_TEXTBOX = 30;
    
    
    - (void)setFrameToTextSize:(CGRect)txtFrame textView:(UITextView *)textView
    {
    
        if(txtFrame.size.height > MAX_HEIGHT_MESSAGE_TEXTBOX)
        {
            //OK, the new frame is to large. Let's use scroll
            txtFrame.size.height = MAX_HEIGHT_MESSAGE_TEXTBOX;
            textView.scrollEnabled = YES;
            [textView scrollRangeToVisible:NSMakeRange([textView.text length], 0)];
        }
        else
        {
            if (textView.frame.size.height < MIN_HEIGHT_MESSAGE_TEXTBOX) {
                 //OK, the new frame is to small. Let's set minimum size
                txtFrame.size.height = MIN_HEIGHT_MESSAGE_TEXTBOX;
            }
            //no need for scroll
            textView.scrollEnabled = NO;
        }
        //set the frame
        textView.frame = txtFrame;
    }
    
    - (void)setframeToTextSize:(UITextView *)textView animated:(BOOL)animated
    {
        //get current height
        CGRect txtFrame = textView.frame;
    
        //calculate height needed with selected font. Note the options.
        //append a new line to make space for the cursor after user hit the return key
        txtFrame.size.height =[[NSString stringWithFormat:@"%@\n ",textView.text]
                               boundingRectWithSize:CGSizeMake(txtFrame.size.width, CGFLOAT_MAX)
                               options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading
                               attributes:[NSDictionary dictionaryWithObjectsAndKeys:textView.font,NSFontAttributeName, nil] context:nil].size.height;
    
        if (animated) {
            //set the new frame, animated for a more nice transition
            [UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveEaseOut |UIViewAnimationOptionAllowAnimatedContent animations:^{
                [self setFrameToTextSize:txtFrame textView:textView];
            } completion:nil];
        }
        else
        {
            [self setFrameToTextSize:txtFrame textView:textView];
        }
    }
    
    - (void)textViewDidChange:(UITextView *)textView
    {
        [self setframeToTextSize:textView animated:YES];
    }
    

    EDIT

    When the string measuring is correct, you might need to change the lineBreakModeon the UITextView‘s textContainer. (NSTextContainer is a new class in iOS7, containing information about how text should be laid out):

    textView.textContainer.lineBreakMode = NSLineBreakByCharWrapping; // default is NSLineBreakByWordWrapping 
    

    Good luck!

    method sizeWithFont:(UIFont *)font constrainedToSize ..." has been deprecated in iOS 7.

    It would function properly.

    Check out its alternate in iOS 7

    Instance Method of NSString

    -(CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:
    
    (NSDictionary *)attributes context:(NSStringDrawingContext *)context
    

    Check this answer out.
    Replacement for deprecated sizeWithFont: in iOS 7?

    I think you want to calculate the content size so that you can increase the content size of scroll view too. if yes Use this link, https://stackoverflow.com/a/19152955/1023083

    for response to “Thanks, but this doesn’t seem to address my issue. I am using both flexible width and height. It seems like i’m getting the correct dimensions returned as the textview scrolls enough in both directions, however the text itself is still being wordwrapped.”

    I fixed this by [textView sizeToFit];