When I call sizeToFit
on one of my views, I noticed that the iOS framework first calls sizeThatFits
and then layoutSubviews
on that view. This is problematic for me because the calculation in my sizeThatFits
depends on the results of my layoutSubviews
. In the following example, a subview gets adjusted in layoutSubviews
and this subview's height is used in sizeThatFits
. Currently my code is not working the order is reversed.
In my view controller's viewDidLoad:
UIView* header = [[MyHeader alloc] init];
[header sizeToFit];
self.tableView.tableHeaderView = header;
[header release];
In my view:
- (void) layoutSubviews {
[super layoutSubviews];
[self.subView sizeToFit];
}
- (CGSize) sizeThatFits:(CGSize)size {
return CGSizeMake(
self.frame.size.width,
self.subView.frame.size.height
);
}
You would want your view to always do The Right Thing(tm), no matter in which order you call things. To accomplish that, I would suggest putting your code that calculates the desired height for your view and the subviews in a separate method. Something along these lines:
- (void)updateSubviewDimensions
{
[self.subview sizeToFit];
// possibly much more code
}
- (void) layoutSubviews {
[super layoutSubviews];
[self updateSubviewDimensions];
}
- (CGSize) sizeThatFits:(CGSize)size {
[self updateSubviewDimensions];
return CGSizeMake(
self.frame.size.width,
self.subView.frame.size.height
);
}
This way, you are not dependent on remembering to call a certain method before calling sizeToFit
, but your view will always do what you want. Plus, your code is less brittle and easier to understand when you look at it a few months from now (or have a different developer look at it).
If your sizeThatFits:
requires layout to be accurate then you need to force a layout (see code below.) But I think this is poorly designed because your layout isn't taking the "size" into account.
- (CGSize) sizeThatFits:(CGSize)size {
[self setNeedsLayout];
[self layoutIfNeeded];
return CGSizeMake(
self.frame.size.width,
self.subView.frame.size.height
);
}
A better approach might be to use auto layout for your subviews, then use systemLayoutSizeFittingSize:
to determine the required size of your view (vs. sizeThatFits:
)
If you can't or don't want to use auto layout then you should consider having separate code paths for actual layout and layout calculation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With