UIView

Every UIView subclass implements the method drawRect:, which contains the drawing code for the view. 

For example, a UIButton's drawRect: method draws a rounded rectangle with a title string in the center.

Each time an instance of UIView needs to be drawn (or redrawn), the system prepares a graphics context specifically for that view. Then the context is activated, and the message drawRect: is sent to the instance of UIView that is being drawn. The graphics context's type is CGContextRef (Core Graphics Context Reference).

A graphics context also stores its drawing state, which inlcudes things like the current drawing color, coordinate system, and the current line width.

- (void)drawRect:(CGRect)rect 
{
// What rectangle am I filling?
CGRect bounds = [self bounds];
// Where is its center?
CGPoint center;
center.x = bounds.origin.x + bounds.size.width / 2.0;
center.y = bounds.origin.y + bounds.size.height / 2.0;
// From the center how far out to a corner?
float maxRadius = hypot(bounds.size.width, bounds.size.height) / 2.0;
// Get the context being drawn upon
CGContextRef context = UIGraphicsGetCurrentContext();
// All lines will be drawn 10 points wide
CGContextSetLineWidth(context, 10);
// Set the stroke color to light gray
[[UIColor lightGrayColor] setStroke];
// Draw concentric circles from the outside in
for (float currentRadius = maxRadius; currentRadius > 0; currentRadius -= 20)
{
CGContextAddArc(context, center.x, center.y,
currentRadius, 0.0, M_PI * 2.0, YES);
CGContextStrokePath(context);
}
}

Notice you are passed a CGRect structure. This is the rectangle that needs to be redrawn, sometimes called the dirty rectangle. A CGRect structure contains the members origin and size. The origin is of type CGPoint and contains two float members: x and y. The size if of type CGSize and also has two float members: width and height.

Remember that a structure is not an objective-c object, so you can't send it messages.

Instantiating a UIView

There are two ways to create an instance of your view:

  • visually choose and position the view while editing the story board file
  • create it programmatically with alloc and initWithFrame: and make it a subview of the window
#import <UIKit/UIKit.h>

//this is a "forward declaration"
@class HypnosisView;
...
HypnosisView *view;

This is a forward declaration for the class HypnosisView.When you forward declare a class, you aren't going as far as importing the header file; You are just informing HypnosisterAppDelegate.h of the class HypnosisView so the compiler can validate it. Forward declaring a class saves time when compiling - especially with large projects.

- (BOOL) application: (UIApplication *) application
didFinishLaunchingWithOptions:(NSDictionary *) launchOptions
{
    // Make a CGRect that is the size of the window
    CGRect wholeWindow = [[self window] bounds];
    // Create an instance of HypnosisView that is the same sizeas the window 
    view = [[HypnosisView alloc] initWithFrame:wholeWindow];
    // Set the background color of that view to "clear"
    [view setBackgroundColor:[UIColor clearColor]];
    // Add the view to the view hierarchy so that it appears onthe window
   [[self window] addSubView:view];
   [[self window] makeKeyAndVisible];
   return YES;
}

Neither HypnosisterAppDelegate nor the window will ever get deallocated because they exist the entire time the application is running.

UIScrollView

UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:wholeWindow];

[[self window] addSubView:scrollView];

[scrollView setContentSize:size];
//center it in the scroll view
CGPoint offset;
offset.x = wholeWindow.size.width*0.5;
offset.y = wholeWindow.size.height*0.5;
[scrollView setContentOffset:offset];

//create the view
view = [[HypnosisView alloc] initWithFrame:reallyBigRect];
[scrollView addSubView:view];

...
}

Zooming

To add zooming, you need to give the scroll view a delegate

@interface HypnosisAppDelegate: NSObject <UIApplicationDelegate, UIScrollViewDelegate>

and in didFinishLaunchingWithOptions...

//enable zooming
[scrollView setMinimumZoomScale:0.5];
[scrollView setMaximumZoomScale:5];
[scrollView setDelegate:self];

in the same file, implement the delegate method viewForZoomingInScrollView:

- (UIView *) viewForZoomingInScrollView: (UIScrollView *)scrollView
{
    return view;
}

You probably don't want to see the time or your remaining battery charge. So, you are going to hide the status bar before you make the window visible.

add a line near the end of application:didFinishLaunchingWithOptions:

[[UIApplication sharedApplication] setStatusBarHidden:YES
                                        withAnimation:UIStatusBarAnimationFade];
[[self window] makeKeyAndVisible];
return YES;

You can also info property list with hidden status bar in project target setting.

Status bar is initially hidden YES

 Retain Cycles

A view hierarchy is made up of many parent-child relationships. When we talk about view hierarchies, we call parents superviews and their children subviews. 

The solution is simple: children should never retain their parents. When you adhere to this rule, deallocating a parent object appropriately release its child objects. If the parent is the only owner of its children, then these child objects are deallocated.

Redrawing Views

When a UIView instance is sent the message setNeesDisplay, the view is marked for re-display. When a view has marked itself for re-display, it is not immediately redrawn, instead, it is added to a list of views that needs updating. Your application is a giant infinite loop called the run loop, The run loop's job is to check for input(a touch,core location updates, data coming in through a network interface, etc. ) and then find the appropriate handlers for that event. 

posted on 2012-06-15 13:37  grep  阅读(416)  评论(0编辑  收藏  举报