Question

I am upgrading my app from iOS6 to iOS7 and I am having some issues with my UIViewControllers layout. In iOS6 I was able to resize my UITextViews dynamically by getting the contentSize property of the textView and then setting its frame property. I would do all the resizing in the viewWillAppear method so that way the view would be resized before it was visible. Now in iOS7 it doesn't work. The only way the contentSize property works is if I set in the viewDidAppear method. I hate doing that because it causes the view to jump after it's already visible. Has anyone figured out how to solve this problem?

Here is my code that no longer works in iOS7:

-(void)viewWillAppear:(BOOL)animated
{
    self.textView = [[UITextView alloc]initWithFrame:CGRectMake(5, 0, 310, 0)];
    self.textView.text = @"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
    [self.view addSubview:self.textView];

    CGRect textViewframe;
    textViewframe = self.textView.frame;
    textViewframe.size.height = [self.textView contentSize].height;
    self.textView.frame = textViewframe;
}
Was it helpful?

Solution

You can call [self.textView layoutIfNeeded] after creating it with the appropriate frame (so it can figure out its max width) then contentSize should be representing the content.

Also: If textView is defined as weak, the text view will be gone on the next line (as ARC adds a release and the optimizer moves it up). They announced this optimization change for Debug (-O0) builds during WWDC.

OTHER TIPS

I met a similar situation as urs. Mine shows with a different bug but due to the same reason: the contentSize property is silently changed by iOS7 incorrectly. Here is how I work around it. Its kinda a ugly fix. Whenever I need to use textView.contentSize, I calculate it by myself.

-(CGSize)sizeOfText:(NSString *)textToMesure widthOfTextView:(CGFloat)width withFont:(UIFont*)font
{
    CGSize size = [textToMesure sizeWithFont:font constrainedToSize:CGSizeMake(width-20.0, FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping];
    return size;
}

then you can just call this function to get the size:

CGSize cont_size =   [self sizeOfText:self.text widthOfTextView:self.frame.size.width withFont:[UIFont systemFontOfSize:15]];

then, don't do the following:

self.contentSize = cont_size;// it causes iOS halt occasionally.

so, just use cont_size directly. I believe it's bug in iOS7 for now. Hopefully apple will fix it soon. Hope this is helpful.

We have the same issue with table views. What is even worse here is that moving to a later lifecycle call like ViewDidAppear may worsen the user experience (from a performance point of view). We try to split the code up and do only the content size setting in ViewWillAppear. But the UI issues then remain.

Having this problem with UITextView as well and I can't depend on contentSize giving the right value to resize my textView, nor does calling layoutIfNeeded on the textView help to get the right value for me. So to solve it, I use sizeThatFits instead of sizeWithFont to figure out UITextView contentSize. SizeWithFont has some subtle differences and sizeThatFits is more proper to use for UITextViews, see UITableViewCell with UITextView height in iOS 7?.

So my solution looks more like:

UITextView* sizingView      = [[UITextView alloc] initWithFrame:textView.frame];
sizingView.attributedText   = textView.attributedText;
CGSize contentSize          = [sizingView sizeThatFits:CGSizeMake(sizingView.frame.size.width, FLT_MAX)];

If you'll notice, I create a new UITextView, copy the attributed text, and get the content size there because unfortunately sizeThatFits has some nasty side effects which can cause the textView not to update properly in iOS 7.0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top