I found this in the Quartz 2D Programming Guide:
To draw to the screen in an iOS application, you set up a UIView object and implement its drawRect: method to perform drawing. The view’s drawRect: method is called when the view is visible onscreen and its contents need updating. Before calling your custom drawRect: method, the view object automatically configures its drawing environment so that your code can start drawing immediately. As part of this configuration, the UIView object creates a graphics context (a CGContextRef opaque type) for the current drawing environment. You obtain this graphics context in your drawRect: method by calling the UIKit function UIGraphicsGetCurrentContext.
Since I am having problems with invalid Context (because it's 0x00 when I go back to re-draw), I was wondering if I could get the current context in the beginning of -drawRect and somehow pass it to the methods I call from within -drawRect?
You can definitely pass CGContextRef to methods called from drawRect: as long as these methods do not save the reference for use outside the duration of the drawRect: call, your code should be fine. However, the context reference that you pass around would be equivalent to the context retrieved through UIGraphicsGetCurrentContext, so I doubt that there is much to gain by adding an extra parameter.
UIGraphicsGetCurrentContext can only be called from drawRect: method (or methods called from it) otherwise it will return nil.
You can use UIGraphicsGetCurrentContext from any method called from -drawRect. It's worth noting that you should not call -drawRect directly when you need to update your view; call -setNeedsDisplay instead.
If you want to use the UIKit drawing system with your own off-screen context, you can use UIGraphicsPushContext to set the current context.
In my experience, passing CGContextRef produces a memory leak that's pretty "fast."
Related
How Can i Call
-(void)drawRect:(CGRect)rect
in https://github.com/stkim1/MTImageMapView/blob/master/MTImageMapView/MTImageMapView.m
From Another UiViewController Periodically With NSTimer
From the documentation:
Discussion
The default implementation of this method does nothing. Subclasses
that use technologies such as Core Graphics and UIKit to draw their
view’s content should override this method and implement their drawing
code there. You do not need to override this method if your view sets
its content in other ways. For example, you do not need to override
this method if your view just displays a background color or if your
view sets its content directly using the underlying layer object.
...
If you subclass UIView directly, your implementation of this method
does not need to call super. However, if you are subclassing a
different view class, you should call super at some point in your
implementation.
This method is called when a view is first displayed or when an event
occurs that invalidates a visible part of the view. You should never
call this method directly yourself. To invalidate part of your view,
and thus cause that portion to be redrawn, call the setNeedsDisplay or
setNeedsDisplayInRect: method instead.
YES i Found The solution i am calling a function with timer at the End of a drawrect function and calling setNeedsDisplay()in it
When subclassing GLKViewController, it has two methods amongst others:
- (void)update,
and - (void)glkView:(GLKView *)view drawInRect:(CGRect)rect.
Both of these methods seem to be called each frame. Documentation reads:
As an alternative to implementing a glkViewControllerUpdate: method in a delegate, your subclass can provide an update method instead. The method must have the following signature:
- (void)update;
Which one should I override in my code, and which of them should contain draw calls?
This thread answers this: Difference between glkView:drawInRect: and glkViewControllerUpdate:? OpenGL ES 2 - iOS
Quoting:
About update() The view controller calls its delegate’s glkViewControllerUpdate: method. Your delegate should update frame data that does not involve rendering the results to the screen.
About drawInRect: the GLKView object makes its OpenGL ES context the current context and binds its framebuffer as the target for OpenGL ES rendering commands. Your delegate method should then draw the view’s contents.
I want to dynamically change the current CGContextRef according to different user actions? Is this possible or is its modification only possible within drawRect: of a view instance? What happens when I call UIGraphicsGetCurrentContext() outside drawRect: and are there any limitations in doing so, is this recommended? Any possible implications I need to consider?
According to the docs the graphics context is only set just before this function is called. This means that if this function is not called it won't be set and if you don't make the system call it again (never do this yourself for that reason) it won't be there either.
Use one of these functions to force the view back into drawRect:
setNeedsDisplay:
setNeedsDisplayInRect:
It doesn't mean you can only do stuff inside drawRect however. This context is sort of globally available at that moment and you can call clean separate functions or even classes for drawing things. Passing the reference to those functions is a clean way to do it.
I'm new to CG drawing, and I'm confused on where the CG code goes.
What is stopping the idea of putting the draw functions in the UIViewController vs the UIView? How should I determine which parts of the CG code should go where? I see that some of the tutorials have code in viewDidLoad from the view controller, but others say it goes in the view. What determines what goes where?
(Yes this is kind of an MVC question, but Im still having trouble differentiating.)
The correct place for custom drawing code is (almost always) in the drawRect method of a subclass of UIView. The usual way to go is to make a custom subclass of UIView and make that the root view of your view controller. In the view controller's loadView method, for example, you can assign self.view = [[MyCustomView alloc] init]; (autorelease that view if you're in non-ARC code!) Then your custom drawing code should go in the drawRect method of MyCustomView.
Core Graphics drawing code can go where ever a valid context is. This means it can go in your own functions if you create your own context.
The reason you generally place Core Graphics drawing code in a UIView subclass is you normally may want to encapsulate the code in a reusable form. But if you were going to create an image from the Core Graphics code you could easily start a new image context, draw, then save the contents of the context into a UIImage. This type of drawing can go anywhere, even a UIViewController. Core Graphics drawing can even be used to generate PDFs. Its simply a simple geometric drawing framework. As long as you have a valid context be it the one created before drawRect: is called in a UIView or a context you created on command.
I'm trying to understand Quartz and getting the context you have to draw on. If I have a function where I create a context, but then I call another function to some other drawing to the same context, do I need to pass the context from the first method to the next? Or can I just use UIGraphicsGetCurrentContext() for any CG methods that require a context since I'm still drawing into the same context?
The docs for UIGraphicsGetCurrentContext() say:
The current graphics context is nil by default. Prior to calling its
drawRect: method, view objects push a valid context onto the stack,
making it current. If you are not using a UIView object to do your
drawing, however, you must push a valid context onto the stack
manually using the UIGraphicsPushContext(_:) function.
So after calling UIGraphicsPushContext() with the context you've created, your other methods can access that context with UIGraphicsGetCurrentContext(). If you're calling UIGraphicsGetCurrentContext() outside of drawRect: and haven't set a context explicitly with UIGraphicsPushContext(), the current graphics context is undefined—and certainly not safe to use.