I was watching a presentation recently where the presenter showed the header for a category that he had added to UIView to make his life a little easier. The point of the talk did not center around the category so I never saw much more than the header, but that was all I needed to recreate it for my use. Here’s the header:
#import <uikit/UIKit.h> @interface UIView (MFAdditions) - (id) initWithParent:(UIView *)parent; + (id) viewWithParent:(UIView *)parent; // Position of the top-left corner in superview's coordinates @property CGPoint position; @property CGFloat x; @property CGFloat y; // Setting size keeps the position (top-left corner) constant @property CGSize size; @property CGFloat width; @property CGFloat height; @end |
As you can see there isn’t a whole lot to this category, but if you’re doing a lot of view manipulation the benefits of it will rapidly become clear. There was one sticky wicket that I hit when implementing this class and it centers around this method:
+ (id) viewWithParent:(UIView *)parent; |
When I first implemented this method I wrote it like so:
+ (id) viewWithParent:(UIView *)parent { return [[[UIView alloc] initWithParent:parent] autorelease]; } |
This was all well and good as long as the only class that I was creating was a UIView, but I ran into trouble when I started creating UIImageViews. Instantiating new UIImageViews worked fine, but as soon as I called a UIImageView-specific method the app would crash:
*** -[UIView setImage:]: unrecognized selector sent to instance 0xd1b350
I struggled with the answer to this one for a while and it wasn’t until I presented my problem to the local CocoaHeads group did I get it all figured out. Here’s the correct way to write this method:
+ (id) viewWithParent:(UIView *)parent { return [[[self alloc] initWithParent:parent] autorelease]; } |
By calling self instead of strongly typing the returned object as a UIView the class would dynamically determine the correct type at runtime.
You can download this category here: UIViewAdditions
I just learned that [[self alloc] init…] trick about a week ago. Not only is it more reliable, but it results in tighter code.
I think the size and position properties are solid wins, but I’m less convinced about adding an incomplete subview to a parent view. Won’t that cause extra update events as you set up the view? If so the only thing I’d add to this is a viewWithFrame.
Pingback: tewha.net » UIView manipulation made easier with a category
Thanks for the category! I wanted to write it myself because I’ve really missed those useful methods when I switched form Qt to Cocoa. But then I decided to do a search and here it is already done for me.
Thanks a lot
Perhaps you were inspired by WWDC 2009 session 128 (prototyping for iPhone)… I’ve been looking for that particular code for a while with no luck, and the presenter didn’t scroll through the whole .m file in his demo. However, what you put together works perfectly and I was able to go through the whole prototyping process easily because of this post – thanks!!
You’re very welcome!
Thanks man! I was looking for the categories of the WWDC 09 session too! Thanks for putting them together!
Pingback: UI Prototyping iPhone Apps | Mobile Solutions Blog
Pingback: UI Prototyping iPhone Apps | Synyx Weblog