Things wot I learnt from Stanford – iPad & iPhone App Development – Fall 2011 – Lecture 4

This lecture was mainly to introduce views.

If you expose a public method that accepts an id, use introspection to check that it is what you expect e.g. if ([theParam isKindOfClass:[NSArray class]]) {…do your stuff…}

Any view has only one superview which can be referenced via the (UIView *)superview @property.

A view can have many (or no) subviews, which can be accessed via the (NSArray *)subviews property. Note that those views later in the array are on top of earlier ones (z-order wise).

In iOS, there will only be one UIWindow right at the top of the view hierarchy. You almost never need to interact with this. Normally the highest view you interact with is the one belonging to the view controller at the top of your hierarchy which controls the whole screen.

Important: Although you add a subview by calling addSubview on the parent view, you remove a subview by calling removeFromSuperview from within the subview – i.e. you ask the subview to remove itself.

The CGFloat structure is used for all view coordinates.

Common structures used for views are:

  • CGPoint  – created with CGPointMake
  • CGSize  – created with CGSizeMake
  • CGRect  – created with CGRectMake

View coordinates and sizes are measured in “points” not pixels. To be future-proof, try to avoid any reference to pixel sizes.

There is a UIView @property CGFloat contentScaleFactor which returns pixels per point on the screen the view is on. This can be used when you really need to know the scaling factor e.g. when drawing charts etc.

Views have 3 important properties related to their location and size:

  • @property CGRect bounds; // Your view’s internal drawing space’s origin and size. Normally you always use bounds coordinates when drawing within your view.
  • @property CGPoint center; // The American centre of your view in it’s superview’s coordinate space.
  • @property CGRect frame; // A rectangle in the superview’s coordinate space that entirely contains your view’s bounds.size.

Use center and frame to position your view within it’s superview (see slide)

Slide from Stanford Lectures Fall 2001To calculate the centre point of a view in bounds coordinate space use:

= (bounds.size.width/2+bounds.origin.x, bounds.size.height/2+bounds.origin.y)

The designated initializer for UIView is initWithFrame:

self.view is always a Controller’s top-level view (i.e. the first subview in the self.subviews array).

One common reason to create a custom view (a UIView subclass) is to handle touch events in a special way.

To draw in a UIView, just override one method:

- (void)drawRect:(GCRect)aRect;

You can optimize by not drawing outside aRect if you want – but this isn’t a requirement.

NEVER, EVER call drawRect: !! – drawing is expensive! Let iOS decide when to do it!!!

Instead, let iOS know that your view’s visual’s need updating with one of these UIView methods:

  • – (void)setNeedsDisplay:
  • – (void)setNeedsDisplayInRect:(CGRect)aRect;

iOS will then call drawRect: for you at an appropriate time.

Like ye olde Windows 3.0 programming days, you draw into a “context“. The context determines where your drawing goes e.g. screen, off-screen bitmap, PDF, printer etc.

drawRect sets up the current context for you – a new one is set up each time drawRect is called – so never cache the current context in drawRect: to user later!

You get the current context within drawRect: by calling:

CGContextRef context = UIGraphicsGetCurrentContext();

This is usually your first line within drawRect:


  1. Get the context.
  2. Define a Path.
  3. Set the graphics stroke and fill
  4. Call CGContextDrawPath


Note that you don’t specify the context for setFill & setStroke – they assume the current context (i.e. the one obtained with UIGraphicsGetCurrentContext())

You can also save and reuse paths using similar functions to the CGContext… ones but prefixed CGPath… This is useful if, for example, you wanted to define a star and then display it 100 times.

UIColor is a class. Methods exist for obtaining common colours e.g. [UIColor redColor]

Call UIColor with setFill and setStroke to return fill and stroke styles in a particular colour.

In iOS, alpha values range from 0.0 (transparent) to 1.0 (opaque).

UIView has a backgroundColor @property which can be set to transparent values.

You have to set UIView @property opaque to NO if you want to use transparency. By default it is YES for performance reasons.

The UIView @property alpha can be used to make the entire view support transparency.

The UIView @property hidden allows you to hide a view. When hidden, it will not be shown on screen and will not handle events. This is a great way to de-clutter a screen by hiding a temporarily unused view. I suspect this is a good performance tip too since it doesn’t handle events when hidden.

Pushing and Popping contexts…

Use UIGraphicsPushContext and UIGraphicsPopContext to preserve a context’s state e.g. if you’re calling a sub-routine which may effect it. See slide.

Preserving Graphics State

Preserving Graphics State. (© Standford University)

Drawing Text in a Custom Font…

You can simply use a UILabel to display text. You can get very fancy using this! However, if you really want to have full control of your font, you can use the UIFont object. See the slide. Perhaps surprisingly, NSString is used to display text in your custom font. These NSString methods are actually defined in UIKit using a mechanism called categories.

Drawing Text

Drawing Text. © Standford University.

Drawing Images…

This refers to bitmap images. Commonly you’d use a UIImageView to display an image (or animation). But this is not the only way. You can even create a bitmap image by drawing with the CGContext functions. See the slides , below…Drawing Images - Slide 1Drawing Images - Slide 2