UIView Manipulation Made Easier with a Category

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

This entry was posted in Cocoa, Sample Code and tagged , , , , , , , .

8 thoughts on “UIView Manipulation Made Easier with a Category

  1. 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.

  2. Pingback: tewha.net » UIView manipulation made easier with a category

  3. THRESHE says:

    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 :)

  4. foz says:

    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!! :)

  5. Michael says:

    You’re very welcome!

  6. David Linsin says:

    Thanks man! I was looking for the categories of the WWDC 09 session too! Thanks for putting them together!

  7. Pingback: UI Prototyping iPhone Apps | Mobile Solutions Blog

  8. Pingback: UI Prototyping iPhone Apps | Synyx Weblog