Because there are too many APIs for the Coregraphics framework, for those who are not very familiar with the first contact or the framework, when drawing, the choice of the API will feel a little confused, and even feel the graphics of iOS is a bit cumbersome. Therefore, this article mainly introduces the drawing method of iOS and analyzes the drawing principle of coregraphics frame.
Introduction of drawing system
iOS drawing framework has a variety of, we usually most commonly used is uikit, its bottom is dependent on coregraphics implementation, and most of the graphical interface is done by Uikit, and UIImage, NSString, Uibezierpath, Uicolor and others know how to draw themselves, and also provide some ways to meet our common drawing needs. In addition to Uikit, there are various frameworks, such as Coregraphics, Core animation,core image,opengl es, to meet different drafting requirements. The general description of each framework is as follows:
UIKit: The most commonly used view frame, the highest package, are OC objects
Coregraphics: The main drawing system, often used to draw custom views, pure C API, using quartz2d to do the engine
Coreanimation: Provides powerful 2D and 3D animation effects
Coreimage: Provides various filter processing for images, such as Gaussian blur, sharpening, etc.
Opengl-es: Mainly used for game drawing, but it is a set of programming specifications, specifically implemented by the device manufacturer
Drawing system
Second, the way of drawing
The actual drawing consists of two parts: view drawing and view layout , which are functionally different, and before understanding these two concepts, you need to know what the drawing cycle is, because it is drawn in the drawing cycle.
Drawing period:
iOS consolidates all drawing requests in a running loop and draws them out at once
cannot be drawn in a child thread, nor can it perform complex operations, otherwise it will cause the main line to incurring
1. View Drawing
Call UIView's DrawRect: method to draw. If you call the Setneedsdisplay method of a view, the view is marked for repainting and is redrawn in the next drawing cycle, calling the DrawRect: Method automatically.
2. View layout
Call the Layoutsubviews method of UIView. If you call a view's Setneedslayout method, the view is marked as requiring a re-layout, and Uikit automatically calls the Layoutsubviews method of the Layoutsubviews method and its child views.
When drawing, we should use the layout as much as possible, and use less drawing, because the layout uses the GPU, and the drawing uses the CPU. The GPU has the advantage of graphics processing, and the CPU has more to deal with and is not good at graphics, so use the GPU as much as possible to work with graphics.
Three, the drawing state switch
iOS graphics have a number of corresponding state transitions, such as: Pop/push, Save/restore, Context/imagecontext, and Cgpathref/uibezierpath, respectively, as described below:
1.pop/push
Setting the context for a drawing
Push: uigraphicspushcontext (context) presses the context into the stack and sets the context to the current drawing contexts
pop: Uigraphicspopcontext pops the context of the top of the stack, restores the previous context, but the drawing state does not change
The view drawn below is black
-(void) DrawRect: (cgrect) rect { [[Uicolor Redcolor] setfill]; Uigraphicspushcontext (Uigraphicsgetcurrentcontext ()); [[Uicolor Blackcolor] setfill]; Uigraphicspopcontext (); Uirectfill (CGRectMake (340/ black color) }
2.save/restore
Set the state of a drawing
Save: Cgcontextsavegstate The current drawing state, just the drawing state, not the drawing context
Restore: Restoring the drawing state you just saved
The view drawn below is red
-(void) DrawRect: (cgrect) rect { [[Uicolor Redcolor] setfill]; Cgcontextsavegstate (Uigraphicsgetcurrentcontext ()); [[Uicolor Blackcolor] setfill]; Cgcontextrestoregstate (Uigraphicsgetcurrentcontext ()); Uirectfill (CGRectMake (+// red color }
3.context/imagecontext
The drawing for iOS must be drawn in one context, so get a context before drawing. If you are drawing a picture, you need to get the context of a picture, and if you are drawing other views, you need a non-picture context. For context, it can be thought of as a canvas, and then a drawing operation on it.
Context: Graphical context, available through Uigraphicsgetcurrentcontext: Gets the context of the current view
imagecontext: Picture context can be obtained by uigraphicsbeginimagecontextwithoptions: Get a picture context, and then after the drawing is done, Call Uigraphicsgetimagefromcurrentimagecontext to get the picture drawn, and finally remember to close the picture context Uigraphicsendimagecontext.
4.cgpathref/uibezierpath
Drawing needs to draw a path, and then render the path, and Cgpathref is the coregraphics framework of the path to draw class, Uibezierpath is encapsulated cgpathref for OC-oriented class, the use of more convenient, But some advanced features are still less than cgpathref.
Iv. Specific Drawing methods
Since iOS commonly used drawing frames have uikit and coregraphics two, so there are a number of ways to draw, here are some of the most common methods of drawing iOS.
1. Context of the picture type
The drawing of the picture context does not need to be done in the DrawRect: method, which can be drawn in a common OC method
Using the Uikit implementation
// get picture context Uigraphicsbeginimagecontextwithoptions (Cgsizemake (100 , 100 ), NO, 0 ); // drawing uibezierpath* p = [Uibezierpath bezierpathwithovalinrect:cgrectmake (0 , 0 , 100 , 100 // uiimage* im = Uigraphicsgetimagefromcurrentimagecontext (); // Close the picture context Uigraphicsendimagecontext ();
Using the Coregraphics implementation
//Get Picture ContextUigraphicsbeginimagecontextwithoptions (Cgsizemake ( -, -), NO,0);//DrawingCgcontextref con =Uigraphicsgetcurrentcontext (); Cgcontextaddellipseinrect (Con, CGRectMake (0,0, -, -)); Cgcontextsetfillcolorwithcolor (Con, [Uicolor Bluecolor]. Cgcolor); Cgcontextfillpath (con);//get a drawn picture from the picture contextuiimage* im =Uigraphicsgetimagefromcurrentimagecontext ();//Close Picture ContextUigraphicsendimagecontext ();
2.drawRect:
In the UIView subclass of the DrawRect: method to implement the graphics redraw, the drawing steps are as follows:
Get context
Draw a graphic
Rendering graphics
Uikit method
-(void) DrawRect: (cgrect) rect { uibezierpath* p = [uibezierpathbezierpathwithovalinrect: CGRectMake (0,0,+)]; [[Uicolor Bluecolor] setfill]; [P fill];}
Coregraphics
-(void) DrawRect: (cgrect) rect { = uigraphicsgetcurrentcontext (); Cgcontextaddellipseinrect (Con, cgrectmake (0,0,+)); Cgcontextsetfillcolorwithcolor (Con, [Uicolor Bluecolor]. Cgcolor); Cgcontextfillpath (con);}
3.drawlayer:incontext:
In the UIView subclass of the Drawlayer:incontext: method can also implement the drawing task, which is a layer of proxy method, and in order to be able to call the method, you need to set the delegate layer proxy object, where the proxy object cannot be a UIView object, Because the UIView object is already a proxy object for its internal root layer (implicit layer), it can be problematic to set it as a proxy object for another layer.
When a view is added to another view, the layer changes as follows:
The calayerdelegate of the view layer is implicitly set to this view
The Drawincontext method that calls this view's Self.layer
Due to the comment of the Drawlayer method: if defined, called by the default implementation Of-drawincontext: illustrates Drawincontext if ([self.delegate Responsetoselector: @selector (drawlayer:incontext:)]) Executes Drawlayer:incontext: method, here we implement the Drawlayer:incontext: So it executes.
[Super Drawlayer:layer Incontext:ctx] will let the system automatically call this view of the DrawRect: method, this self.layer draw out
Adds a child layer to the Self.layer, when the [layer Setneedsdisplay] is called, and the Drawincontext method of the layer is called automatically
If DrawRect is not overridden, the Drawincontext method of its layer is not called, and the Drawlayer:incontext method is not called
Invoke the drawlayer:incontext of the internal root layer:
//If DrawRect is not overridden, the Drawincontext method of its layer is not called, and the Drawlayer:incontext method is not called-(void) DrawRect: (cgrect) rect{NSLog (@"2-drawrect:"); NSLog (@"the cgcontext:%@ in DrawRect.", Uigraphicsgetcurrentcontext ()); //The current graphical context that is obtained is exactly what is passed in Drawlayer .[Super Drawrect:rect];}#pragmamark-calayerdelegate-(void) Drawlayer: (Calayer *) layer Incontext: (cgcontextref) ctx{NSLog (@"1-drawlayer:incontext:"); NSLog (@"the cgcontext:%@ in Drawlayer.", CTX); //If this sentence is removed, DrawRect will not be executed!!!!!!!![Super Drawlayer:layer incontext:ctx];}
To invoke the drawlayer:incontext of an external proxy object:
Since the UIView object cannot be set to the Calayerdelegate proxy, we need to create a NSObject object and then implement the Drawlayer:incontext: method so that the desired graph can be drawn in the proxy object. In addition, when you set up the agent, you do not have to obey the Calayerdelegate proxy protocol, that is, this method is NSObject, and you do not need to explicitly specify the protocol.
//MYLAYERDELEGATE.M- (void) Drawlayer: (Calayer *) layer Incontext: (cgcontextref) ctx{cgcontextaddellipseinrect (CTX, CGRectMake ( -, -, -, -)); Cgcontextsetfillcolorwithcolor (CTX, [Uicolor Bluecolor]. Cgcolor); Cgcontextfillpath (CTX);}//VIEWCONTROLLER.M@interfaceViewcontroller () @property (nonatomic, Strong)IDmylayerdelegate;@end@implementationViewcontroller- (void) Viewdidload {//set the delegate of a layer to a NSObject subclass object_mylayerdelegate =[[Mylayerdelegate alloc] init]; MyView*myview =[[MyView alloc] initWithFrame:self.view.bounds]; [Self.view Addsubview:myview]; Calayer*layer =[Calayer layer]; Layer.backgroundcolor=[Uicolor Magentacolor]. Cgcolor; Layer.bounds= CGRectMake (0,0, -, -); Layer.anchorpoint=Cgpointzero; Layer.Delegate=_mylayerdelegate; [Layer Setneedsdisplay]; [Myview.layer Addsublayer:layer];}
Detailed implementation process
When UIView needs to be displayed, its inner layer prepares a cgcontextref (graphics context) and calls the Drawlayer:incontext of delegate (here is UIView): method, And pass in the Cgcontextref object that is already ready. and UIView in the Drawlayer:incontext: method will also call their own DrawRect: method. Usually in DrawRect: through Uigraphicsgetcurrentcontext () is the Cgcontextref object that is passed in by the layer, all the drawings completed in DrawRect: are filled into the cgcontextref of the layer, It is then copied to the screen.
iOS drawing framework analysis as above, if there are shortcomings, welcome to point out the common progress. (This picture is from the Internet, the copyright belongs to the original author all)
Source: http://www.cocoachina.com/ios/20170809/20187.html
iOS Drawing frame coregraphics analysis