Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIGraphicsGetCurrentContext vs UIGraphicsBeginImageContext/UIGraphicsEndImageContext

I am new to these parts of iOS API and here are some questions that are causing an infinite loop in my mind

  1. Why does ..BeginImageContext have a size but ..GetCurrentContext does not have a size? If ..GetCurrentContext does not have a size, where does it draw? What are the bounds?

  2. Why did they have to have two contexts, one for image and one for general graphics? Isn't an image context already a graphic context? What was the reason for the separation (I am trying to know what I don't know)

like image 289
Nihat Avatar asked Feb 14 '14 17:02

Nihat


2 Answers

UIGraphicsGetCurrentContext() returns a reference to the current graphics context. It doesn't create one. This is important to remember because if you view it in that light, you see that it doesn't need a size parameter because the current context is just the size the graphics context was created with.

UIGraphicsBeginImageContext(aSize) is for creating graphics contexts at the UIKit level outside of UIView's drawRect: method.

Here is where you would use them.

If you had a subclass of UIView you could override its drawRect: method like so:

- (void)drawRect:(CGRect)rect
{
    //the graphics context was created for you by UIView
    //you can now perform your custom drawing below

    //this gets you the current graphic context
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    //set the fill color to blue
    CGContextSetFillColorWithColor(ctx, [UIColor blueColor].CGColor);

    //fill your custom view with a blue rect
    CGContextFillRect(ctx, rect);
}

In this case, you didn't need to create the graphics context. It was created for you automatically and allows you to perform your custom drawing in the drawRect: method.

Now, in another situation, you might want to perform some custom drawing outside of the drawRect: method. Here you would use UIGraphicsBeginImageContext(aSize)

You could do something like this:

UIBezierPath *circle = [UIBezierPath
                        bezierPathWithOvalInRect:CGRectMake(0, 0, 200, 200)];  

UIGraphicsBeginImageContext(CGSizeMake(200, 200));

//this gets the graphic context
CGContextRef context = UIGraphicsGetCurrentContext();

//you can stroke and/or fill
CGContextSetStrokeColorWithColor(context, [UIColor blueColor].CGColor);
CGContextSetFillColorWithColor(context, [UIColor lightGrayColor].CGColor);
[circle fill];
[circle stroke];

//now get the image from the context
UIImage *bezierImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

UIImageView *bezierImageView = [[UIImageView alloc]initWithImage:bezierImage];

I hope this helps to clear things up for you. Also, you should be using UIGraphicsBeginImageContextWithOptions(size, opaque, scale). For further explanation of custom drawing with graphics contexts, see my answer here

like image 186
daveMac Avatar answered Oct 14 '22 04:10

daveMac


You are slightly confused here.

As the name suggests UIGraphicsGetCurrentContext grabs the CURRENT context, thus it doesn't need the size, it grabs an existing context and returns it to you.

So when is there an existing context? Always? No. When the screen is rendering a frame, a context is created. This context is available in the drawRect: function, which is called to draw the view.

Normally, your functions aren't called in drawRect:, so they don't actually have a context available. This is when you call UIGraphicsBeginImageContext.

When you do that, you create an image context, then you can grab said context with UIGraphicsGetCurrentContext and work with it. And thus, you have to remember to end it with UIGraphicsEndImageContext

To clear things up further - if you modify the context in drawRect:, your changes will be shown on screen. In your own function, your changes don't show up anywhere. You have to extract the image in the context through the UIGraphicsGetImageFromCurrentImageContext() call.

Hope this helps!

like image 24
Jack Avatar answered Oct 14 '22 03:10

Jack