views:

428

answers:

1

This is pretty high level but Cocoa is big and I'm still trying to get my head around it. Can someone validate my expectations...

Say I'd like to have a variable number of views (images of cars for example) on the screen that the user can touch and move around. Would you start by subclassing UIView with UIImage property (as opposed to UIImageView or a UIButton). Then instantiate say "red", "blue" and "yellow" cars in the view controller and store them in an NSMutableArray?

I could set up the initial layout in Interface Builder but not sure how to connect the custom objects back to the array? Some need to start in a rotated state. Haven't been able to figure out how to rotate in IB either?!? So I'm guessing in this case it'd be better to build the initial state in code before view displays.

Finally, once displayed, handle the touchesBegan, Ended, etc., the animation and the logic of adding, removing and counting "cars" in the view controller?

A: 

Hey Meltemi,

It sounds like you're on the right track. I'll try to address all of your expectations one at a time:

  1. The views onscreen could be a custom UIView subclass or UIImageViews. You might want to think about other functionality you want to add in the future. The UIView approach offers the most flexibility, and would also allow you to handle rotation by drawing the car image manually. To do that, create a subclass of UIView, give it an image property and a rotation property, and then override the "drawRect:(CGRect)rect" function to draw the image.

  2. Putting an array of the cars in the view controller sounds great.

  3. Storing the initial layout in an Interface Builder NIB file is usually the best bet. It allows you to easily change the interface in the future, and cuts out a lot of boilerplate code that is required to create and position things onscreen.

That said, it's not possible to bind a bunch of views to a single array outlet. In this particular case, I would implement the view controller's "viewDidLoad" function to create several cars. You were on the right track!

It's not possible to setup rotation in Interface Builder because it's not a popular option. You can implement rotation using CAAnimation transforms to set a rotation property and then manually draw the image at an angle.

Hope that helps!

EDIT: Here's some sample code to draw an image at an angle. It uses Quartz (also known as Core Graphics) - so there's a lot more information available in the Apple documentation

- (void)drawRect:(CGRect)r
{
    // get the drawing context that is currently bound
    CGContextRef c = UIGraphicsGetCurrentContext();

    // save it's "graphics state" so that our rotation of the coordinate space is undoable.
    CGContextSaveGState(c);

    // rotate the coordinate space by 90º (in radians). In Quartz, images are 
    // always drawn "up," but using CTM transforms, you can change what "up" is!
    // Can also use TranslateCTM and ScaleCTM to manipulate other properties of coordinate space.
    CGContextRotateCTM(c, M_PI / 2);

    // draw an image to fill our entire view. Note that if you want the image to be semi-transparent,
    // the view must have opaque = NO and backgroundColor = [UIColor clearColor]!
    CGContextDrawImage(c, self.bounds, [[UIImage imageNamed:@"image_file.png"] CGImage]);

    // restore the graphics state. We could just rotate by -M_PI/2, but for complex transformations
    // this is very handy.
    CGContextRestoreGState(c);
}
Ben Gotow
this is very helpful. can you point to more docs or examples of "manually" drawing the image at, say, a 90° angle? I'm not familiar with Affine Transforms. Is that what I want?
Meltemi
Affine transforms will allow you to rotate, scale, or skew an entire view - for example a button - and you could use that to rotate the image. A complicated car model might have multiple rotating pieces though, so using a lower-level drawing technique to draw images at an angle would be better. See example code above!
Ben Gotow
Great! thanks..but i'm just getting a black box?!? i replaced my drawRect code { [carImage drawAtPoint:(CGPointMake(0.0, 0.0))]; } with yours change Draw Image line to: CGContextDrawImage(c, self.bounds, [carImage CGImage]); . image used to draw (just not rotated) before. now it's black...and still not rotated. any ideas?
Meltemi