UIView with Auto layout, get his size

autolayout, cocoa-touch, ios, iphone, uiview

Solution

`sizeToFit` is the wrong API to use if you're using autolayout.

The correct api to use for autolayout is `UIView` `systemLayoutSizeFittingSize`:, most likely passing `UILayoutFittingCompressedSize`. This will return a CGSize which is the minimum size that can bound the view with its specified constraints.

Check this link

EDIT: In response to the additional code that was posted...

I've never used the Masonry library before but it's neat!

`UILabels` provide an `intrinsicContentSize` that is large enough to display their text. In order to calculate this size for multi-line text the label needs to know a single dimension that will be fixed, and that is the desired-width dimension via the `preferredMaxLayoutWidth` property. If you don't provide a `preferredMaxLayoutWidth` value (defaults to 0), the label calculates an intrinsic content size AS IF it were laying out a single line of text.

In your code you never set the label's `preferredMaxLayoutWidth` so any layout performed by autolayout that relies on the intrinsicContentSize of the label will not be what you're expecting.

I took your code and distilled it into a new example, which you should be able to copy/paste into a clean viewcontroller subclass:

#import "Masonry.h"

@interface TSViewController ()
@end

@implementation TSViewController
{
    UIScrollView*   _scrollView;
    UIView*         _containerView;

    UILabel*        _titleLabel;
    UILabel*        _contentLabel;
}

- (void) viewDidLoad
{
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor darkGrayColor];

    // create/configure our scrollview
    _scrollView = [UIScrollView new];
    _scrollView.translatesAutoresizingMaskIntoConstraints = NO;
    _scrollView.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];
    [self.view addSubview: _scrollView];

    // create/configure our container
    _containerView = [UIView new];
    _containerView.translatesAutoresizingMaskIntoConstraints = NO;
    _containerView.backgroundColor = [UIColor yellowColor];
    [_scrollView addSubview: _containerView];

    // create/configure our content - title and content labels
    _titleLabel = [UILabel new];
    _titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _titleLabel.numberOfLines = 1;
    _titleLabel.font = [UIFont fontWithName: @"Courier" size: 80];
    _titleLabel.text = @"Lorem Ipsum";
    _titleLabel.backgroundColor = [UIColor lightGrayColor];
    _titleLabel.textAlignment = NSTextAlignmentCenter;
    [_containerView addSubview: _titleLabel];

    _contentLabel = [UILabel new];
    _contentLabel.translatesAutoresizingMaskIntoConstraints = NO;
    _contentLabel.numberOfLines = 0;
    _contentLabel.font = [UIFont fontWithName: @"Courier" size: 40];
    _contentLabel.text = self.loremIpsum;
    [_containerView addSubview: _contentLabel];

    // configure constraints for each view:

    [_scrollView mas_makeConstraints: ^(MASConstraintMaker *make) {

        // glue the scrollview to its superview with a 20 point inset:

        make.top.equalTo( self.view.mas_top ).with.offset( 20 );
        make.left.equalTo( self.view.mas_left ).with.offset( 20 );
        make.right.equalTo( self.view.mas_right ).with.offset( -20 );
        make.bottom.equalTo( self.view.mas_bottom ).with.offset( -20 );
    }];

    [_containerView mas_makeConstraints: ^(MASConstraintMaker *make) {

        // per the iOS 6.0 Release Notes, this is how to use auto-layout for a container view
        // inside a scrollview.  basically, tie the edges of the containerview to the scrollview.
        // http://developer.apple.com/library/ios/#releasenotes/General/RN-iOSSDK-6_0/
        // see section "Here are some notes regarding Auto Layout support for UIScrollView"

        make.top.equalTo( _scrollView.mas_top );
        make.left.equalTo( _scrollView.mas_left );
        make.right.equalTo( _scrollView.mas_right );
        make.bottom.equalTo( _scrollView.mas_bottom );

        // match the width of the containerview to the scrollview width:
        make.width.equalTo( _scrollView.mas_width );

        // match the height of the containerview to the intrinsic height of the contentlabel + 100 points for our fixed height title

        // (this is the magical part.)
        make.height.equalTo( _contentLabel.mas_height ).with.offset( 100 );
    }];

    [_titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {

        // tie the contentlabel edges to the sides of its container:
        make.top.equalTo( _containerView.mas_top ).with.offset(0);
        make.left.equalTo( _containerView.mas_left ).with.offset(0);
        make.right.equalTo( _containerView.mas_right ).with.offset(0);

        // fixed height
        make.height.equalTo( @100 );
    }];

    [_contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {

        // tie top edge to the bottom of our title
        make.top.equalTo( _titleLabel.mas_bottom );

        // tie the remaining edges to the sides of the container:
        make.left.equalTo( _containerView.mas_left );
        make.right.equalTo( _containerView.mas_right );
        make.bottom.equalTo( _containerView.mas_bottom );
    }];
}

- (void) viewWillLayoutSubviews
{
    // perform a scrollview layout so the containerView width will be set
    [_scrollView setNeedsLayout];
    [_scrollView layoutIfNeeded];

    // update the preferred layout width of the content label;
    // this affects the label's intrinsicContentSize and will force our constraints to be recalculated
    CGFloat preferredWidth = _containerView.frame.size.width;
    _contentLabel.preferredMaxLayoutWidth = preferredWidth;


    // we don't need this since the scrollview is fully using autolayout to adjust the content-size.  but just to show that it works:

    CGSize fittingSize = [_containerView systemLayoutSizeFittingSize: UILayoutFittingCompressedSize];

    NSLog( @"container fitting size: %@", NSStringFromCGSize( fittingSize ));
}

- (NSString*) loremIpsum
{
    return @"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing <br>Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type<br> and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
}

@end

And, here's the output from systemLayoutSizeFittingSize when the constraints are all working nicely:

2013-08-05 15:01:16.309 testLabelConstraints[8265:c07] container fitting size: {721, 6868}

Problem

I have one UIView witch is populated with content programmatically. Layout in this UIView is made using Auto-layout. This view needs to be subview of one UIScrollView, and it needs to scroll vertically. I have code like this: ``` // self.scrollview is defined in IB and it has constraints to edges (margin:0 0 0 0) UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, MAXFLOAT)]; [contentView setTranslatesAutoresizingMaskIntoConstraints:YES]; // Then I call some my parser which add subviews to the contentView and layout them using constraints. [self.scrollview addSubview:contentView]; [contentView setNeedsLayout]; [contentView layoutIfNeeded]; // Now, I need to know height of the contentView to be able to set contentSize to self.scrollview ``` // UPDATE Ok, I have this UILabel, added to self.content which is UIView created with: `[[UIView alloc] initWithFrame:CGRectMake(self.layoutMargin, self.layoutMargin, 1024 - self.layoutMargin*2, 100)]);` This self.content view is just container for me, which needs to be placed in some `UIScrollView`. I need the height of the self.content to set contentSize of the `UIScrollView`. ``` [self.content setTranslatesAutoresizingMaskIntoConstraints:YES]; [self.content setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; [self.content setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; UILabel *textlabel = [[UILabel alloc] init]; UIFont *font; font = [UIFont fontWithName:@"InterstatePlus-Regular" size:16]; UIFont *bold; bold = [UIFont fontWithName:@"InterstatePlus-Bold" size:16]; NSDictionary *style = @{ @"$default" : @{NSFontAttributeName : font}, @"b" : @{NSFontAttributeName : bold}, @"em" : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Italic" size:14]}, @"h1" : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:48]}, @"h2" : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:36]}, @"h3" : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:32]}, @"h4" : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:24]}, @"h5" : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:18]}, @"h6" : @{NSFontAttributeName : [UIFont fontWithName:@"HelveticaNeue-Medium" size:16]} }; [textlabel setNumberOfLines:0]; NSError *error = nil; NSString *string = @"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing <br>Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type<br> and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."; NSString *replacedString = [string stringByReplacingOccurrencesOfString:@"<br>" withString:@"\n"]; NSAttributedString *attributedString = [SLSMarkupParser attributedStringWithMarkup:replacedString style:style error:&error]; NSMutableAttributedString *mutAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:attributedString]; NSInteger strLength = [attributedString length]; NSMutableParagraphStyle *paragraphstyle = [[NSMutableParagraphStyle alloc] init]; [mutAttributedString addAttribute:NSParagraphStyleAttributeName value:paragraphstyle range:NSMakeRange(0, strLength)]; if (mutAttributedString) { textlabel.attributedText = mutAttributedString; } [textlabel setTranslatesAutoresizingMaskIntoConstraints:NO]; [textlabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; [textlabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical]; textlabel.textAlignment = NSTextAlignmentLeft; [textlabel setTextColor:[UIColor blackColor]]; [textlabel setBackgroundColor:[UIColor clearColor]]; textlabel.lineBreakMode = NSLineBreakByWordWrapping; [textlabel setNumberOfLines:0]; [self.content addSubview:textlabel]; [textlabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.content.mas_top).with.offset(0); make.right.equalTo(self.content.mas_right).with.offset(0); make.height.equalTo(@1200); make.left.equalTo(self.content.mas_left).with.offset(0); }]; [self.containerView addSubview:self.content]; [self.containerView setBackgroundColor:[UIColor redColor]]; [self.content setBackgroundColor:[UIColor yellowColor]]; CGSize s = [self.content systemLayoutSizeFittingSize:UILayoutFittingCompressedSize]; NSLog(@"Size: %f %f", s.width, s.height); ``` This is Log: Size: 17713.000000 0.000000 And it looks like: http://d.pr/i/Rxku

Original source