質問

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"];
}
役に立ちましたか?

解決

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.

他のヒント

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.

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.

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top