Don't know the final frame size of UIView until after drawRect?

Go To


I'm drawing a grid of data in a UIView with drawRect, of which I won't know the final size when the UIView is created because the number of columns and rows is dynamic. Sure I could do the calculations before creating the UIView, but that doesn't really make sense, because I'll also be doing those calculations in the UIView subclass, and would rather not have to extract that.

So how do I handle this? Do I init with a very large frame and adjust it after drawRect is done?

I will also be setting this view as the content of a UIScrollView in case its too large to be viewed in the area allotted for it.

The view I'm going to be drawing looks something like this: Pricing Grid

2012-04-03 20:41
by Bob Spryn
See my answer to this question: - Brenden 2013-11-21 20:49


  • Add a method in your view that determines how large it should be, based on its data. This needs to be separate from drawRect:.
  • In your view controller, when you're setting up the view, call that method to get that size.
  • Then set your view's bounds and/or frame to that size.
  • And also set the scroll view's contentSize to that size.

The key concept is: Separate the ideas of "determine how large my view's stuff is" and "draw my view's stuff". Right now, you are doing the size computation while you draw, but you need to be able to do it earlier.

If you want to get fancy, you could look into overriding layoutSubviews in a superview of your view -- that would be a good place to check if the view's desired size has changed, and then update the view's size and the scroll view's contentSize. But it isn't necessary to do that to start.

2012-04-04 04:44
by Kurt Revis
I just thought of this same thing, but you confirming it makes me think its right. :) Thanks - Bob Spryn 2012-04-04 05:33
layoutSubviews gets called more than once. See: - Brenden 2013-11-21 20:50
Yes, you do need to be careful in -layoutSubviews and only do the work if you need to. That's why I said "check if the view's desired size has changed". If -layoutSubviews is called again, but nothing has changed, then you don't need to do anything - Kurt Revis 2013-11-22 00:48


Perhaps others have another solution but I think that in your case I would override setFrame: and call setNeedsDisplay so that drawRect will be called after your frame changes. Have you tried this approach already?

2012-04-03 21:12
by clstroud
Hmm.. that seems a little hacky. I'll wait a bit to see what other suggestions come up. Thanks - Bob Spryn 2012-04-03 22:31
Perhaps... but I believe you are expecting it to work more like layoutSubviews, which is called every time the frame changes. drawRect will only be called when something specifically asks it to re-paint the view - clstroud 2012-04-03 22:35
One other thing though, are you using init or initWithFrame: to initialize your custom UIView - clstroud 2012-04-03 22:36
I'm not using either yet. I was confused at to how to handle that when I don't know my frame to start with - Bob Spryn 2012-04-04 01:00
Ah okay so if you don't know the view's frame at all when instantiating, I still think your only options are going to be to call setNeedsDisplay from an overridden setFrame: or perhaps call it from the parent view controller's layoutSubviews method (not recommended). Otherwise I'm curious to see what others suggest - clstroud 2012-04-04 01:13