0% found this document useful (0 votes)
33 views

Stanford CS193p: Developing Applications For iOS Fall 2011

This document summarizes a Stanford course on developing iOS applications. It discusses views, the view hierarchy, and coordinates in iOS. Views represent rectangular areas that can contain other views. The UIWindow is at the top of the view hierarchy. Views use frames and centers to position themselves, and bounds to define their drawing space. Custom views can be created by subclassing UIView and overriding the drawRect method to use Core Graphics APIs to draw paths, shapes, and text.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
33 views

Stanford CS193p: Developing Applications For iOS Fall 2011

This document summarizes a Stanford course on developing iOS applications. It discusses views, the view hierarchy, and coordinates in iOS. Views represent rectangular areas that can contain other views. The UIWindow is at the top of the view hierarchy. Views use frames and centers to position themselves, and bounds to define their drawing space. Custom views can be created by subclassing UIView and overriding the drawRect method to use Core Graphics APIs to draw paths, shapes, and text.
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

Stanford CS193p

Developing Applications for iOS Fall 2011

Stanford CS193p Fall 2011

Views
A view (i.e. UIView subclass) represents a rectangular area
Denes a coordinate space

Draws and handles events in that rectangle Hierarchical


A view has only one superview - (UIView *)superview But can have many (or zero) subviews - (NSArray *)subviews Subview order (in subviews array) matters: those later in the array are on top of those earlier

UIWindow
The UIView at the top of the view hierarchy Only have one UIWindow (generally) in an iOS application Its all about views, not windows

Stanford CS193p Fall 2011

Views
The hierarchy is most often constructed in Xcode graphically
Even custom views are added to the view hierarchy using Xcode (more on this later).

But it can be done in code as well


- (void)addSubview:(UIView *)aView; - (void)removeFromSuperview;

Stanford CS193p Fall 2011

View Coordinates
CGFloat CGPoint
Just a oating point number, but we always use it for graphics. C struct with two CGFloats in it: x and y.
CGPoint p = CGPointMake(34.5, 22.0); p.x += 20; / move right by 20 points /

CGSize

C struct with two CGFloats in it: width and height.


CGSize s = CGSizeMake(100.0, 200.0); s.height += 50; / make the size 50 points /

taller

CGRect

C struct with a CGPoint origin and a CGSize size.


CGRect aRect = CGRectMake(45.0, 75.5, 300, 500); aRect.size.height += 45; / make the rectangle 45 / aRect.origin.x += 30;

points taller / move the rectangle to the right 30 points /


Stanford CS193p Fall 2011

(0,0)

Coordinates
Units are points (not pixels)

increasing x (400, 35)

Origin of a views coordinate system is upper left


Usually you dont care about how many pixels per point are on the screen youre drawing on. Fonts and arcs and such automatically adjust to use higher resolution. However, if you are drawing something detailed (like a graph, hint, hint), you might want to know. There is a UIView property which will tell you: @property CGFloat contentScaleFactor; / returns pixels per point on the screen this view is on / This property is not (readonly), but you should basically pretend that it is for this course.

Views have 3 properties related to their location and size


@property CGRect bounds;

/ your views internal drawing spaces origin and size / The bounds property is what you use inside your views own implementation. It is up to your implementation as to how to interpret the meaning of bounds.origin. @property CGPoint center; / the center of your view in your superviews coordinate space / @property CGRect frame; / a rectangle in your superviews coordinate space which entirely / / contains your views bounds.size /
Stanford CS193p Fall 2011

increasing y

Coordinates
Use frame and center to position the view in the hierarchy
These are used by superviews, never inside your UIView subclasss implementation. You might think frame.size is always equal to bounds.size, but youd be wrong ...

140 , 65 30 0, 22 5

320
2 50
0 0, 20 0
ew Vi

View A

Because views can be rotated (and scaled and translated too). View Bs bounds = ((0,0),(200,250)) View Bs frame = ((140,65),(320,320)) View Bs center = (300,225) View Bs middle in its own coordinate space is
(bound.size.width/2+bounds.origin.x, bounds.size.height/2+bounds.origin.y) which is (100,125) in this case.

320

Views are rarely rotated, but dont misuse frame or center by assuming that.

Stanford CS193p Fall 2011

Creating Views
Most often you create views in Xcode
Of course, Xcodes palette knows nothing about a custom view class you might create. In that case, you drag out a generic UIView from the palette and use the Inspector to change the class of the UIView to your custom class (demo of this later).

How do you create a UIView in code (i.e. not in Xcode)?


Just use alloc and initWithFrame: (UIViews designated initializer).

Example
CGRect labelRect = CGRectMake(20, 20, 50, 30); UILabel *label = [[UILabel alloc] initWithFrame:labelRect]; label.text = @Hello!; [self.view addSubview:label];

/ well talk about self.view later / / (it is a Controllers top-level view) /

Stanford CS193p Fall 2011

Custom Views
When would I want to create my own UIView subclass?
I want to do some custom drawing on screen. I need to handle touch events in a special way (i.e. different than a button or slider does) Well talk about handling touch events later. For now were focussing on drawing.

Drawing is easy ... create a UIView subclass & override 1 method


- (void)drawRect:(CGRect)aRect;

You can optimize by not drawing outside of aRect if you want (but not required).

NEVER call drawRect:!! EVER! Or else!


- (void)setNeedsDisplay;

Instead, let iOS know that your views visual is out of date with one of these UIView methods:
- (void)setNeedsDisplayInRect:(CGRect)aRect; It will then set everything up and call drawRect: for you at an Obviously, the second version will call your drawRect: with only

appropriate time rectangles that need updates

Stanford CS193p Fall 2011

Custom Views
So how do I implement my drawRect:?
Use the Core Graphics framework

The API is C (not object-oriented) Concepts


Get a context to draw into (iOS will prepare one each time your drawRect: is called) Create paths (out of lines, arcs, etc.) Set colors, fonts, textures, linewidths, linecaps, etc. Stroke or ll the above-created paths

Stanford CS193p Fall 2011

Context
The context determines where your drawing goes
Screen (the only one were going to talk about today) Offscreen Bitmap PDF Printer

For normal drawing, UIKit sets up the current context for you
But it is only valid during that particular call to drawRect: A new one is set up for you each time drawRect: is called So never cache the current graphics context in drawRect: to use later!

How to get this magic context?

Call the following C function inside your drawRect: method to get the current graphics context ...
CGContextRef context = UIGraphicsGetCurrentContext();

Stanford CS193p Fall 2011

Dene a Path
Begin the path
CGContextBeginPath(context);

Move around, add lines or arcs to the path


CGContextMoveToPoint(context, 75, 10); CGContextAddLineToPoint(context, 160, 150);

Stanford CS193p Fall 2011

Dene a Path
Begin the path
CGContextBeginPath(context);

Move around, add lines or arcs to the path


CGContextMoveToPoint(context, 75, 10); CGContextAddLineToPoint(context, 160, 150); CGContextAddLineToPoint(context, 10, 150);

Stanford CS193p Fall 2011

Dene a Path
Begin the path
CGContextBeginPath(context);

Move around, add lines or arcs to the path


CGContextMoveToPoint(context, 75, 10); CGContextAddLineToPoint(context, 160, 150); CGContextAddLineToPoint(context, 10, 150);

Close the path (connects the last point back to the rst)
CGContextClosePath(context);

/ not strictly required /

Stanford CS193p Fall 2011

Dene a Path
Begin the path
CGContextBeginPath(context);

Move around, add lines or arcs to the path


CGContextMoveToPoint(context, 75, 10); CGContextAddLineToPoint(context, 160, 150); CGContextAddLineToPoint(context, 10, 150);

Close the path (connects the last point back to the rst)
CGContextClosePath(context);

/ not strictly required /

Actually the above draws nothing (yet)!

You have to set the graphics state and then ll/stroke the above path to see anything.

Stanford CS193p Fall 2011

Dene a Path
Begin the path
CGContextBeginPath(context);

Move around, add lines or arcs to the path


CGContextMoveToPoint(context, 75, 10); CGContextAddLineToPoint(context, 160, 150); CGContextAddLineToPoint(context, 10, 150);

Close the path (connects the last point back to the rst)
CGContextClosePath(context);

/ not strictly required /

You have to set the graphics state and then ll/stroke the above path to see anything. [[UIColor greenColor] setFill]; / object-oriented convenience method (more in a moment) /
[[UIColor redColor] setStroke]; CGContextDrawPath(context, kCGPathFillStroke);

Actually the above draws nothing (yet)!

/ kCGPathFillStroke is a constant /
Stanford CS193p Fall 2011

Dene a Path
It is also possible to save a path and reuse it
Similar functions to the previous slide, but starting with CGPath instead of CGContext We wont be covering those, but you can certainly feel free to look them up in the documentation

Stanford CS193p Fall 2011

Graphics State
UIColor
UIColor *red = [UIColor redColor]; / class method, returns autoreleased instance / UIColor *custom = [[UIColor alloc] initWithRed:(CGFloat)red // 0.0 to 1.0 blue:(CGFloat)blue green:(CGFloat)green alpha:(CGFloat)alpha]; [red setFill]; [custom set]; // 0.0 to 1.0 (opaque)

class for setting colors

/ ll color set in current graphics context (stroke color not set) / / sets both stroke and ll color to custom (would override [red setFill]) /

Drawing with transparency in UIView

Note the alpha above. This is how you can draw with transparency in your drawRect:. UIView also has a backgroundColor property which can be set to transparent values. Be sure to set @property BOOL opaque to NO in a view which is partially or fully transparent. If you dont, results are unpredictable (this is a performance optimization property, by the way). The UIView @property CGFloat alpha can make the entire view partially transparent.

Stanford CS193p Fall 2011

View Transparency
What happens when views overlap? Default drawing is opaque
As mentioned before, subviews list order determines whos in front Lower ones (earlier in subviews array) can show through transparent views on top of them Transparency is not cheap (performance-wise)

Also, you can hide a view completely by setting hidden property


@property (nonatomic) BOOL hidden;

/ view will not be on screen and will not handle events / This is not as uncommon as you might think On a small screen, keeping it de-cluttered by hiding currently unusable views make sense
myView.hidden = YES;

Stanford CS193p Fall 2011

Graphics State
Some other graphics state set with C functions, e.g. ...
CGContextSetLineWidth(context, 1.0);

/ line width in points (not pixels) /

CGContextSetFillPattern(context, (CGPatternRef)pattern, (CGFloat[])components);

Stanford CS193p Fall 2011

Graphics State
Special considerations for dening drawing subroutines
What if you wanted to have a utility method that draws something You dont want that utility method to mess up the graphics state of the calling method Use push and pop context functions.
- (void)drawGreenCircle:(CGContextRef)ctxt { UIGraphicsPushContext(ctxt); [[UIColor greenColor] setFill];

/ draw my circle /
UIGraphicsPopContext(); } - (void)drawRect:(CGRect)aRect { CGContextRef context = UIGraphicsGetCurrentContext(); [[UIColor redColor] setFill];

/ do some stuff /
[self drawGreenCircle:context]; }

/ do more stuff and expect ll color to be red /


Stanford CS193p Fall 2011

Drawing Text
Use UILabel to draw text, but if you feel you must ... Use UIFont object in UIKit to get a font
UIFont *myFont = [UIFont systemFontOfSize:12.0]; UIFont *theFont = [UIFont fontWithName:@Helvetica size:36.0]; NSArray *availableFonts = [UIFont familyNames];

Then use special NSString methods to draw the text


NSString *text =

...;

/ NSString instance method / How much space will a piece of text will take up when drawn? CGSize textSize = [text sizeWithFont:myFont]; / NSString instance method /
[text drawAtPoint:(CGPoint)p withFont:theFont];

You might be disturbed that there is a Foundation method for drawing (which is a UIKit thing). But actually these NSString methods are dened in UIKit via a mechanism called categories. Categories are an Objective-C way to add methods to an existing class without subclassing. Well cover how (and when) to use this a bit later in this course.
Stanford CS193p Fall 2011

Drawing Images
Use UIImageView to draw images, but if you feel you must ...
Well cover UIImageView later in the course.

Create a UIImage object from a le in your Resources folder


UIImage *image = [UIImage imageNamed:@foo.jpg];

Or create one from a named le or from raw data


(of course, we havent talked about the le system yet, but ...)
UIImage *image = [[UIImage alloc] initWithContentsOfFile:(NSString *)fullPath]; UIImage *image = [[UIImage alloc] initWithData:(NSData *)imageData];

Or you can even create one by drawing with CGContext functions


UIGraphicsBeginImageContext(CGSize);

/ draw with CGContext functions /


UIImage *myImage = UIGraphicsGetImageFromCurrentContext(); UIGraphicsEndImageContext();
Stanford CS193p Fall 2011

Drawing Images
Now blast the UIImages bits into the current graphics context
UIImage *image = ...; [image drawAtPoint:(CGPoint)p]; [image drawInRect:(CGRect)r]; [image drawAsPatternInRect:(CGRect)patRect;

/ p is upper left corner of the image / / scales the image to t in r / / tiles the image into patRect /

Aside: You can get a PNG or JPG data representation of UIImage


NSData *jpgData = UIImageJPEGRepresentation((UIImage *)myImage, (CGFloat)quality); NSData *pngData = UIImagePNGRepresentation((UIImage *)myImage);

Stanford CS193p Fall 2011

Next Time
Tomorrow
Source Control

Next Week

Protocols (a little more Objective C) Demo of custom UIView View Controller Lifecycle Controllers of Controllers Storyboarding Universal Applications

Stanford CS193p Fall 2011

You might also like