41

I'm a new developer iOS.

I use auto-layout.

I have a problem. I can not get real size of UIView after constraints.

Example, when I want get size of UIView with constraint

self.container.frame.size.height

It alway return 550 for all device size. But I can see it have difference size when I run it on difference device.

Thanks

Hemang
  • 26,840
  • 19
  • 119
  • 186
Chicken
  • 447
  • 1
  • 4
  • 8

8 Answers8

55

Before your "getting real size code", insert the following code:

[view setNeedsLayout];
[view layoutIfNeeded];
Allen
  • 6,745
  • 5
  • 41
  • 59
  • 3
    IMHO no need to call both `[view setNeedsLayout]` and `[view layoutIfNeeded]`, only the latter was enough for me in `viewWillLayoutSubviews` – schmidt9 Oct 03 '16 at 08:04
  • 3
    **Swift 4 Answer:** Just what @Allen said actually, just insert view.setNeedsLayout() view.layoutIfNeeded() above the code that you are trying to get the true size of things you are using. Because viewDidAppear code applies after the animations which may look ugly for some people. – MertEjd Jun 22 '18 at 07:59
22

Since everybody assumes the access is done via a UIViewController and not inside a UIView subclass, the answers don't prove really useful. The correct way to get the correct size of a UIView subclass is in layoutSubviews.

Leandros
  • 16,805
  • 9
  • 69
  • 108
  • I calculate the size in layoutSubviews. But it only works if I call layoutIfNeeded just before the height calculation. calling self.setNeedsLayout, also works. I wounder which one is best? – Sentry.co Nov 21 '18 at 05:54
17

The simplest solution is to just run that code in -viewDidAppear: (after autolayout has been run).

Oxcug
  • 6,524
  • 2
  • 31
  • 46
  • Thanks. But how to do if i want get real size in viewDidLoad. Have you got any solution? – Chicken Dec 26 '14 at 06:01
  • @Chicken See Allen's solution. This will force auto-layout to be run immediately. You really should avoid doing that sort of thing especially more than once. – Oxcug Jun 29 '17 at 02:25
14

Seems like - (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize; is what you are looking for:

Return Value
The size of the view that satisfies the constraints it holds.

Discussion
Determines the best size of the view considering all constraints it holds and those of its subviews.

https://developer.apple.com/documentation/uikit/uiview/1622624-systemlayoutsizefittingsize?language=objc

Pierre
  • 390
  • 3
  • 10
13

You could just use the UIView method intrinsicContentSize

enter image description here

which you can read about https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/#//apple_ref/occ/instm/UIView/intrinsicContentSize

Abizern
  • 146,289
  • 39
  • 203
  • 257
  • 1
    This should be the correct answer. If you are doing auto layout programmatically and not explicitly setting frames, this is the proper way to get the height/weight based on content. – Marquis103 Jun 27 '17 at 19:12
  • @Marquis103 `intrinsicContentSize` ignores (as the name suggests, and is also mentioned in the screenshot above) all constraints affecting the view. For example, a label's intrinsic content size is simply the frame it would take to display the label's text. But if your label has a "width <= 200" constraint, that would be ignored. However, OP explicitly asked for the view's size "after constraints". – lukas Apr 27 '21 at 12:35
9

This is awesome.

If you want to get frame without using layoutsubviews method during autolayout usage, Use this one:

dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"View frame: %@", NSStringFromCGRect(view.frame));
    })
SamSol
  • 2,885
  • 6
  • 37
  • 56
  • Thank you for this idea. Nothing is strange here: you are asking this code to be called after getting back to the main dispatch queue. This will happen after auto-layout took place. Very useful indeed! – ishahak Mar 30 '16 at 02:40
  • 1
    Thanks. Not strange as Sam says. Also a better solution than subclass views just for this. – Juan Pedro Lozano Jun 30 '16 at 17:40
3

[view layoutIfNeed] save me.

Use this method to force the layout of subviews before drawing. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root.

After invoke this method, I can get actual size of custom view in xib. Thanks a lot to @Allen and the author.

Chiakie
  • 271
  • 1
  • 2
  • 12
  • This is what I needed, my view was not getting the correct size in 'viewDidLayoutSubviews' so I called layoutIfNeeded in the call and everything is working fine – josher932 Nov 28 '22 at 17:35
2

The best moment is during the viewDidLayoutSubviews because it happens before the viewDidAppearso you still are able to do some modifications before the view is displayed.

Zaphod
  • 6,758
  • 3
  • 40
  • 60