I really do not get it :(


#1

Hello all,

it really doesn’t make sense to me why we can change this line :

by

I understand the first line. It’s in C and we specify the context and the stroke color for it.

But what about the second line?

First it seems we are dynamically creating an UIColor object. Then we are sending it the setStroke message. But :

  • How can this object know to set the stroke of a context since we never tell to this object wich context to target?
  • Can we simply create an object like this [UIColor colorWithRed:0.6 green:0.6 blue:0.6 alpha:1.0] without alloc nor init, nor pointer?

I would appreciate any insight there. I really don’t get how this object can tell the context wich stroke to use without even knowing its existence :slight_smile:

Thank you


#2

I struggled a little with this same concept at first too. I think the secret is in the [color=blue]UIGraphicsGetCurrentContext()[/color] function. I’m just beginning my iOS journey too but it sounds like the current device context is available, and anyone can call this function get to it. According to the documentation, the view object squirrels away the context making it available to callers of the UIGraphicsGetCurrentContext() function.

It’s under assumption that UIColor’s [color=blue]setStroke[/color] method simply calls UIGraphicsGetCurrentContext() to get the graphics context then calls [color=blue]CGContextSetStrokeColor()[/color] or something similar.

Again, I’m just a beginner to and I’m making some assumptions so if I’m wrong, please correct me.


#3

In your drawRect: method, you call a function UIGraphicsGetCurrentContext(). This gives you a pointer to the current context of the application. Using this pointer as an argument to CGContextSetStrokeColor allows you to specify that the context’s stroke color be changed.

This is no different than what setStroke does - it also calls UIGraphicsGetCurrentContext to determine the current context. Thus, the implementation of setStroke looks like this:

- (void)setStroke
{
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    float r, g, b, a;
    [self getRed:&r green:&g blue:&b alpha:&a];
    CGContextSetRGBStrokeColor(ctx, r, g, b, a);
}

#4

Thank you Joe :slight_smile:


#5

Hey guys,

Maybe I’m just not locking in on this, so please speak up if you can clarify.

I understand that there is a context (in this case “ctx”) which is either written explicitly in methods or accessed via the UIColor superclass… but I guess I just don’t understand why it’s all one fluid connection.

Why are we having to use the same context for the circles, then the string of text (“are you getting sleepy?”), then the shadow and eventually… the crosshair in the silver challenge? Everything else in iOS seems so artfully separated and singularly made into objects. Why are we, in this case, having to commit to this one ctx instance, structure our code appropriately around that?

Seems so strange to me that, just with vector view drawing, we are using calls like [[UIColor redColor] setFill] and so on and not referring to specific pointers.

I’m sure it’s a broad explanation, but any enlightenment would be awesome. Felt like I was really making progress, then I hit this chapter and felt absolutely confused after multiple reads and walk throughs.


#6

The for the more curious in this chapter may give you some insight, but the basic idea is such:

When a view is asked to redraw itself (the first time it appears on the screen or when it is sent setNeedsDisplay), it gets added to a queue of all views waiting to be redrawn. When an event is finished processing, the following steps are taken for each view in the redraw queue:

  1. Create a CGContextRef.
  2. Make this context “the” current context.
  3. Call the view’s drawRect: method
  4. Get the image out of “the” current context.
  5. Set the view’s “image” to that image.

The reason you use the same context is because every drawing operation will result in one single image that will become that view’s image. Thus, it makes sense to the circles, text, etc. onto the same context because you want it all to be in the same image. (If you did not want it to be in the same image, you would create separate view objects.)

But you shouldn’t think about the globalness of it all. What you should think about is the drawRect: method - it gets called automatically for you, and when it is called, all you have to do is draw to this context you are provided, and the result of all drawing into that context becomes the image for the view running drawRect:.