5

When is it possible to know the exact size of a UIViewController's view?

The Problem

I have a multi-line UILabel whose frame depends of its text and the width of the parent view. Given that I need to position other views below the UILabel, it's important to make its frame cover exactly the space of the text.

I currently calculate the size like this on viewDidLoad:

labelSize = [text sizeWithFont:font constrainedToSize:CGSizeMake(self.view.frame.size.width, MAX_HEIGHT)];

The problem is that the width of the parent view changes when the UIViewController is used as a modal form sheet or a popover. If I use autoresizingMask the frame of the UILabel is adjusted accordingly, but it no longer is an exact fit for the text.

Where can I calculate the frame of this UILabel knowing the exact size of the UIViewController's view?

Debugging Efforts

This is the result of printing self.view.frame when showing the UIViewController as a modal form sheet (UIModalPresentationFormSheet).

viewDidLoad: (0.000000;0.000000;320.000000;480.000000)
viewWillAppear: (0.000000;0.000000;768.000000;960.000000)
afterDelay: (0.000000;0.000000;540.000000;576.000000)

The code that produces the above output:

- (void)viewDidLoad {
    [super viewDidLoad];
    [Utils logFrame:self.view.frame tag:@"viewDidLoad"];
}

- (void) viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [Utils logFrame:self.view.frame tag:@"viewWillAppear"];
    [self performSelector:@selector(afterDelay) withObject:nil afterDelay:0.1];
}

- (void) afterDelay {
    [Utils logFrame:self.view.frame tag:@"afterDelay"];
}
hpique
  • 119,096
  • 131
  • 338
  • 476
  • If autoresizingMask is not doing what you want, you will have to make a UIView subclass and implement the layoutSubviews method to position everything manually. – Mike Weller Aug 16 '11 at 11:58

4 Answers4

2

That's because your UIViewController's root view is using autoresizingMask. I don't think there is a "perfect timing" to detect the size of your UIViewController's root view unless you override your root view's 'layoutSubviews' method.

If you don't want your view to be automatically resized, just don't use autoresizing and set the size by yourself, it will always be the same size you expected.

If you are not sure what kind of autoresizingMasks your root view is using, NSLog is your friend.

xuzhe
  • 5,100
  • 22
  • 28
1

This looks like a bug, the value should be known in viewWillAppear.

The alternative is to subclass your UIView and override layoutSubviews there to arrange the subviews based on content. You'll then have to call [self.view setNeedsLayout] from your view controller every time you update the contents of the label. The system will call it if the view resizes, so that should have you covered.

joerick
  • 16,078
  • 4
  • 53
  • 57
  • Are you sure that the frame should be known in viewWillAppear? I checked the documentation and it doesn't say anything about it. – hpique Aug 16 '11 at 11:38
  • Also, overriding layoutSubviews looks like it might be a solution. However, I was hoping for something less.. daunting to solve such a trivial thing like sizing an UILabel. – hpique Aug 16 '11 at 11:39
  • @hgpc no not sure, but my intuition tells me it should be.... it's not *too* daunting...! It's just an extra class you have to have kicking around. – joerick Aug 16 '11 at 15:49
0

Try this for finding the label size,

labelSize = [text sizeWithFont:font constrainedToSize:CGSizeMake(self.label.frame.size.width, MAX_HEIGHT)];

Instead of using the view's width, use the label's width in the constrain size. This should be available in the viewDidLoad, viewDidApper methods of the view controller.

Nithin
  • 6,435
  • 5
  • 43
  • 56
  • Can you elaborate further? I define the width of the label, so I'm not sure how it can provide me the real width of the view. – hpique Aug 16 '11 at 10:47
0

try viewWillAppear. There is no reason for not knowing the size before the the view is about to shown

CinoSS
  • 1
  • viewWillAppear does not provide the right size when the view is displayed as a modal form sheet, at least. – hpique Aug 16 '11 at 10:33