views:

43

answers:

1

Starting off with a default "View based" application I create a new view (ViewToDisplay, class that inherits from UIView) and inside this view I create a layer (LayerToDisplay). The view draws something around the perimeter of the frame, and so does the layer but this time with dotted lines. This is to show / prove that the layer covers the entire view.

Here's the relevant code from ViewToDisplay.m

- (void) awakeFromNib
{
    ld = [[LayerToDisplay alloc] init];
    ld.frame = self.frame;
    [self.layer addSublayer:ld];
    [ld setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextBeginPath(context);
    CGContextSetRGBStrokeColor(context, 255/255.0, 0/255.0, 0/255.0, 1);
    CGContextSetLineWidth(context, 1);

    CGContextMoveToPoint(context, 0, 0);
    CGContextAddLineToPoint(context, 320, 460);
    CGContextAddLineToPoint(context, 0, 460);
    CGContextAddLineToPoint(context, 320, 0);

    CGContextClosePath(context);
    CGContextStrokePath(context);
}

and the layer (LayerToDisplay.m)

- (void)drawInContext:(CGContextRef)context
{
    CGContextBeginPath(context);

    CGContextSetRGBStrokeColor(context, 0/255.0, 255/255.0, 0/255.0, 1);
    CGContextSetLineWidth(context, 1);

    CGFloat dashes[]={3,6};
    CGContextSetLineDash(context, 0, dashes, 3);

    CGContextMoveToPoint(context, 0, 0);
    CGContextAddLineToPoint(context, 320, 460);
    CGContextAddLineToPoint(context, 0, 460);
    CGContextAddLineToPoint(context, 320, 0);

    CGContextClosePath(context);
    CGContextStrokePath(context);
}

If I change the default ApplicationNameViewController.xib's view to my class (ViewToDisplay) it works as expected. If I try to instantiate this from the application delegate the view shows up correctly but the layer is shifted down, i.e. what the layer draws doesn't overlap what the view draws.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

    ViewToDisplay *vd = [[ViewToDisplay alloc] init];
    // doesn't seem to matter
    //[vd setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight];
    vd.frame = [UIScreen mainScreen].applicationFrame;
    // call manually so that the layer gets created
    [vd awakeFromNib]; 
    [window addSubview:vd]; 

    //[window addSubview:viewController.view];
    [window makeKeyAndVisible];

    return YES;
}

So, I'm trying to figure out what's the difference between creating / instantiating a view with these two ways. What does the automatic process (when changing an XIB's class to ViewToDisplay) do that I'm not doing in code?

Thank you!

P.S. this is an exercise in understanding how it works behind the scenes, not in using best practices.

+3  A: 

In awakeFromNib use ld.frame = self.bounds; instead of ld.frame = self.frame;.

To explain what's going on - if the view is loaded by view-controller, that view has its frame starting at point (0, 0). If you are using UIScreen's applicationFrame, that is positioned down by size of the status bar.

Michal
That was it, and it makes sense. Thanks.
pbz