0

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;
}
denvdancsk
  • 3,033
  • 2
  • 26
  • 41

4 Answers4

10

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.

Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • Thanks but it didn't work. I'm pretty sure it's a bug in iOS7 that they need to fix. – denvdancsk Oct 01 '13 at 15:09
  • But it would not be the first iOS 7 bug :( – Martin Ullrich Oct 01 '13 at 15:49
  • Wait it did work!!! When I first implemented that method I tried it with the parent as in [self.view layoutIfNeeded]; and it didn't work. I tried it again your way on each individual textView of my content and it works!!! Thanks again. – denvdancsk Oct 01 '13 at 16:23
1

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.

long long
  • 122
  • 8
  • Thanks. I tried a similar formula like yours with similar results. I noticed that when I logged the cont_size.height in viewWillAppear and then compared it with what the contentSize.height would be in the viewDidAppear method I got slightly different results. It would usually be off by about off 4-6 points (and some change) depending on what font and frame dimensions were used. I guess I'll use this for now though until apple fixes the issue. – denvdancsk Oct 01 '13 at 15:07
  • `sizeWithFont` is depricated in iOs7 – Nikita Took Jul 25 '14 at 07:00
0

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.

falkse
  • 85
  • 1
  • 5
0

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.

Community
  • 1
  • 1
DogpatchTech
  • 468
  • 4
  • 11
  • Hmm.... layoutIfNeeded should work. I tested it and logged the results and everything matched up. I'm curious as to why it wouldn't work for you. How did you implement it? – denvdancsk Oct 10 '13 at 06:00
  • Yeah, it was strange that it didn't line up for me... I called it technically from viewWillAppear, but the first time through it didn't seem to work properly even with all the text set, so I went with the other method. I create my views largely programmatically so that may have affected it, too. – DogpatchTech Oct 18 '13 at 21:07