views:

47

answers:

1

Hi all, I have a UIView based control which I need to resize depending on various criteria and properties of the control. I'm not sure if the way I'm doing it is the best way but so far it's the only one I've found that seems to work. Because the size of the control is dependant on various properties, I cannot set the size in a constructor.

I have a method called setupControl: which contains all the code to finish the setup based on the properties set. I don't want setupControl: called manually, so in drawRect I detect if I need to call it and then queue a selector like this:

[self performSelector:@selector(setupControl)withObject:self afterDelay:0];
return;

At the bottom of setupControl: I then do:

[self setNeedsDisplay];
self.hidden = NO;

I've also overridden the initWithFrame: and initWithDecoder: constructors so that they set the UIView to be hidden to start with until the setup code is executed. The idea being to eliminate any "flashes" on the display as the control resizes.

As I said this works fine, the controls can be drawn ay size is the xib file and then set themselves to the correct size at run time.

My question is whether this method of queuing a selector, exiting the drawRect: and then using a setNeedsDisplay is the only way to do this? O is there some method I haven't found that I can override? or something else?

+1  A: 

What you probably want to override is layoutSubviews (http://developer.apple.com/library/ios/documentation/uikit/reference/UIView_Class/UIView/UIView.html#//apple_ref/occ/instm/UIView/layoutSubviews) rather than drawRect as you're changing the layout, not implementing custom drawing.

You may also have to use a custom setter for any properties that change the size of the view and call [self setNeedsLayout] in the setter to make sure your layoutSubviews method is called before your view size is computed.

Robot K
Hmm, the control does not have any subviews (I am doing some drawing in drawRect: and want to size the control according to that drawing). So I'm not sure that that is the right method.
Derek Clarkson
However I did just read the sizeToFit: and sizeThatFits: doco. But it wasn't clear how they fit into the sceme of things. I'd really like to see a document that outlines the calls that are made to and from controls as they are instantiated so I can understand the startup cycle.
Derek Clarkson
Basically, you should ignore that you don't have any subviews and pretend like you do. Override sizeThatFits: and return the size you want your view to have. In layoutSubviews, compute the size and position of all the "elements" in your view (and store the results in some ivars) and then do your drawing in drawRect:. Note that you want to do as little computation in drawRect: as possible. Keep it fast. Do your computations in layoutSubviews instead.
Robot K
Yep that worked. I used layoutSubviews for final setup and added a call in it to sizeToFit:, then computed the size in sizeThatFits:. Much neater all around and I was able to remove some other code as a result. Thanks.
Derek Clarkson