Quartz 2D是Core Graphics框架的一部分,是一个强大的二维图像绘制引擎。Quartz 2D在UIKit中也有很好的封装和集成,我们日常开发时所用到的UIKit中的组件都是由Core Graphics进行绘制的。不仅如此,当我们引入UIKit框架时系统会自动引入Core Graphics框架,并且为了方便开发者使用在UIKit内部还对一些常用的绘图API进行了封装。
一般步骤
1、获取绘图上下文
2、创建并设置路径
3、将路径添加到上下文
4、设置上下文状态
5、绘制路径
图形上下文CGContextRef代表图形输出设备(也就是绘制的位置),包含了绘制图形的一些设备信息。Quartz 2D中所有对象都必须绘制在图形上下文。
class CGView: UIView {
override func drawRect(rect: CGRect) {
super.drawRect(rect)
// 1、 获取上下文对象
let context = UIGraphicsGetCurrentContext()
// 2、 创建路径对象
let path = CGPathCreateMutable()
CGPathMoveToPoint(path, nil, 10, 30)
CGPathAddLineToPoint(path, nil, 10, 100)
CGPathAddLineToPoint(path, nil, 150, 100)
// 3、 添加路径到图形上下文
CGContextAddPath(context, path)
// 4、 设置图形上下文状态属性
CGContextSetRGBStrokeColor(context, 253/255.0, 245/255.0, 220/255.0, 1) //设置笔触颜色
CGContextSetRGBFillColor(context, 1, 61/255.0, 78/255.0, 1) //设置填充色
CGContextSetLineWidth(context, 5) //设置线条宽度
CGContextSetLineCap(context, CGLineCap.Round ) // 设置顶点样式
CGContextSetLineJoin(context, CGLineJoin.Round) //设置连接点样式
/*设置线段样式
phase:虚线开始的位置 这里设置为0
lengths:虚线长度间隔
count:虚线数组元素个数
*/
let lengths: [CGFloat] = [5,7] //长度间隔
CGContextSetLineDash(context, 0 , lengths, 2)
let color = UIColor.grayColor().CGColor //颜色转化,由于Quartz 2D跨平台,所以其中不能使用UIKit中的对象,但是UIkit提供了转化方法
/*设置阴影
context:图形上下文
offset:偏移量
blur:模糊度
color:阴影颜色
*/
CGContextSetShadowWithColor(context, CGSizeMake(2, 2), 0.8, color)
// 5、 绘制图像到指定图形上下文
/*
CGPathDrawingMode是填充方式,枚举类型
Fill:只有填充(非零缠绕数填充),不绘制边框
EOFill:奇偶规则填充(多条路径交叉时,奇数交叉填充,偶交叉不填充)
Stroke:只有边框
FillStroke:既有边框又有填充
EOFillStroke:奇偶填充并绘制边框
*/
CGContextDrawPath(context, CGPathDrawingMode.EOFillStroke) //最后一个参数是填充类型
}
}
UIKit已经为我们准备好了一个上下文,在drawRect:方法(这个方法在loadView、viewDidLoad方法后执行)中我们可以通过UIKit封装函数UIGraphicsGetCurrentContext()方法获得这个图形上下文。
然后我们按照上面说的步骤一步一步的执行下来得到结果:
然后在vc的viewDidLoad中加入代码:
let cgView = CGView()
cgView.frame = CGRectMake(100, 100, 200, 200)
self.view.addSubview(cgView)
得到结果如图:
上面的步骤略显复杂,其实代码还可以简化
我们再创建一个继承自UIView的子类 CGViewTwo
class CGViewTwo: UIView {
override func drawRect(rect: CGRect) {
super.drawRect(rect)
// 1、 获取上下文对象
let context = UIGraphicsGetCurrentContext()
// 2、绘制路径(相当于前面创建路径并添加路径到图形上下文两步操作)
CGContextMoveToPoint(context, 10, 30)
CGContextAddLineToPoint(context, 10, 100)
CGContextAddLineToPoint(context, 150, 100)
// 封闭路径:直接调用路径封闭方法
CGContextClosePath(context)
// 3、 设置图形上下文属性
/*
set(): 设置笔触和填充颜色
setFill(): 设置填充颜色
setStroke(): 设置笔触颜色
*/
// UIColor.redColor().set()
UIColor.redColor().setFill()
UIColor.redColor().setStroke()
// 4、 绘制路径
CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
}
}
上面代码精简了许多,Core Graphics 内部对创建对象添加到上下文这两步操作进行了封装,可以一步完成
继续在刚的vc的viewDidLoad:中加入代码:
let cgView = CGView()
cgView.frame = CGRectMake(100, 100, 200, 200)
self.view.addSubview(cgView)
let cgViewTwo = CGViewTwo()
cgViewTwo.frame = CGRectMake(100, 350, 200, 150)
self.view.addSubview(cgViewTwo)
绘制矩形
我们再来创建一个继承自 UIView的子类CGViewThree
class CGViewThree: UIView {
override func drawRect(rect: CGRect) {
super.drawRect(rect)
// 1、 获取上下文对象
guard let context = UIGraphicsGetCurrentContext() else { return }
// 画矩形
self.drawRectWithContext(context)
}
/**
画 矩形
- parameter context: 上下文对象
*/
private func drawRectWithContext(context: CGContext) {
let rect = CGRectMake(20, 0, 280, 50)
CGContextAddRect(context, rect)
UIColor.blueColor().set()
CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
}
}
在vc对应viewDidLoad中加入此View
let cgViewThree = CGViewThree()
cgViewThree.frame = CGRectMake(100, 400, 200, 150)
self.view.addSubview(cgViewThree)
运行后结果:
其实UIKit对绘图方法的封装,使用起来更加简单。我们可以直接使用
直接在CGViewThree中继续添加方法
/**
画 矩形, 用UIKit封装的方法
- parameter context: 上下文对象
*/
private func drawRectByUIKitWithContext(context: CGContext) {
let rect = CGRectMake(0, 0, self.bounds.size.width, 50)
let rect2 = CGRectMake(0, 70, self.bounds.size.width, 50)
UIColor.yellowColor().set()
UIRectFill(rect)
UIColor.redColor().set()
UIRectFill(rect2)
}
然后在drawRect中调用 运行结果
绘制椭圆和圆
继续在CGViewThree中添加方法
/**
画 椭圆, 宽高一样就是正圆
- parameter context: 上下文对象
*/
private func drawEllipse(context: CGContext) {
let rect = self.bounds
CGContextAddEllipseInRect(context, rect)
UIColor.purpleColor().set()
CGContextDrawPath(context, CGPathDrawingMode.Fill)
}
这里宽高设置的不一样 只要把宽和高设置一样就是正圆
在drawRect中添加此方法
运行结果:
绘制弧形
/**
画 弧形
- parameter context: 上下文对象
*/
private func drawArc(context: CGContext) {
/*
添加弧形对象
x:中心点x坐标
y:中心点y坐标
radius:半径
startAngle:起始弧度
endAngle:终止弧度
closewise:是否逆时针绘制,0则顺时针绘制
*/
CGContextAddArc(context, self.bounds.size.width * 0.5, self.bounds.size.height * 0.5, 50, 0, CGFloat(M_PI), 0)
UIColor.greenColor().set()
CGContextDrawPath(context, CGPathDrawingMode.Fill)
}
和上面一样 添加到drawRect
运行结果
绘制贝塞尔曲线
在Quartz 2D中曲线绘制分为两种:二次贝塞尔曲线和三次贝塞尔曲线。二次曲线只有一个控制点,而三次曲线有两个控制点,如下图所示:
下面演示下绘制方法:
/**
绘制 贝塞尔曲线
- parameter context: 上下文对象
*/
private func drawCurve(context: CGContext) {
// 绘制曲线
CGContextMoveToPoint(context, 20, 50) //移动到起始位置
/**
绘制二次贝塞尔曲线
c:图形上下文
cpx:控制点x坐标
cpy:控制点y坐标
x:结束点x坐标
y:结束点y坐标
*/
CGContextAddQuadCurveToPoint(context, 120, 0, 120, 50)
CGContextMoveToPoint(context, 20, 100)
/*绘制三次贝塞尔曲线
c:图形上下文
cp1x:第一个控制点x坐标
cp1y:第一个控制点y坐标
cp2x:第二个控制点x坐标
cp2y:第二个控制点y坐标
x:结束点x坐标
y:结束点y坐标
*/
CGContextAddCurveToPoint(context, 70, 0, 120, 200, 170, 100)
UIColor.yellowColor().setStroke()
UIColor.redColor().setFill()
CGContextDrawPath(context, CGPathDrawingMode.FillStroke)
}
上面所有方法加入到drawRect
文字绘制
Core Graphics不仅可以画图还能绘制文字
这个页面已经放不下了 开一个新的页面 继续,后面我会把所有代码上传github 供大家参考
创建一个新的继承自UIView的类CGViewFour
添加下面方法
/**
文字绘制
- parameter context: 上下文对象
*/
private func drawText(context: CGContext) {
let str = "使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制使用CoreGraphics进行文字绘制"
let rect = CGRectMake(20, 20, 280, 200)
let font = UIFont.systemFontOfSize(16)
let color = UIColor.redColor()
let style = NSMutableParagraphStyle()
style.alignment = NSTextAlignment.Left
(str as NSString).drawInRect(rect, withAttributes: [NSFontAttributeName:font,NSForegroundColorAttributeName:color,NSParagraphStyleAttributeName:style])
}
声明了一个字符串,设置了绘制区间、字体颜色段落属性等
画好之后 还在在drawRect中调用
override func drawRect(rect: CGRect) {
super.drawRect(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
self.drawText(context)
}
结果:
文字已经正确的绘制到视图上
图像绘制
当然Core Graphics也能绘制图像
很简单
/**
图像绘制
- parameter context: 上下文对象
*/
private func drawImage(context: CGContextRef) {
let img = UIImage.init(named: "haha")
img?.drawInRect(CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height))
//从某一点开始绘制
img?.drawAtPoint(CGPoint(x: 0, y: 0))
}
可以从某点开始绘制也可以指定位置区域
绘制渐变
Quartz 2D的渐变方式分为两种:
线性渐变线:渐变色以直线方式从开始位置逐渐向结束位置渐变
径向渐变:以中心点为圆心从起始渐变色向四周辐射,直到终止渐变色
/**
绘制线性渐变
- parameter context: 上下文
*/
func drawLinearGradient(context:CGContextRef){
//使用rgb颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
/*
指定渐变色
space:颜色空间
components:颜色数组,注意由于指定了RGB颜色空间,那么四个数组元素表示一个颜色(red、green、blue、alpha),
如果有三个颜色则这个数组有4*3个元素
locations:颜色所在位置(范围0~1),这个数组的个数不小于components中存放颜色的个数
count:渐变个数,等于locations的个数
*/
let compoents:[CGFloat] = [ 248.0/255.0,86.0/255.0,86.0/255.0,1,
249.0/255.0,127.0/255.0,127.0/255.0,1,
1.0,1.0,1.0,1.0]
let locations:[CGFloat] = [0,0.4,1]
let gradient = CGGradientCreateWithColorComponents(colorSpace, compoents, locations, locations.count)
/*
绘制线性渐变
context:图形上下文
gradient:渐变色
startPoint:起始位置
endPoint:终止位置
options:绘制方式,DrawsBeforeStartLocation 开始位置之前就进行绘制,到结束位置之后不再绘制,
DrawsAfterEndLocation开始位置之前不进行绘制,到结束点之后继续填充
*/
CGContextDrawLinearGradient(context, gradient , CGPointZero, CGPointMake(self.frame.size.width,100), CGGradientDrawingOptions.DrawsAfterEndLocation)
}
径向渐变
新建一个CGViewSix
/**
径向渐变绘制
- parameter context: 上下文
*/
func drawRadialGradient(context:CGContextRef){
//使用rgb颜色空间
let colorSpace = CGColorSpaceCreateDeviceRGB()
/*
指定渐变色
space:颜色空间
components:颜色数组,注意由于指定了RGB颜色空间,那么四个数组元素表示一个颜色(red、green、blue、alpha),
如果有三个颜色则这个数组有4*3个元素
locations:颜色所在位置(范围0~1),这个数组的个数不小于components中存放颜色的个数
count:渐变个数,等于locations的个数
*/
let compoents:[CGFloat] = [ 248.0/255.0,86.0/255.0,86.0/255.0,1,
249.0/255.0,127.0/255.0,127.0/255.0,1,
1.0,1.0,1.0,1.0]
let locations:[CGFloat] = [0,0.4,1]
let gradient = CGGradientCreateWithColorComponents(colorSpace, compoents, locations, locations.count)
/*
绘制线性渐变
context:图形上下文
gradient:渐变色
startPoint:起始位置
startRadius:起始半径(通常为0,否则在此半径范围内容无任何填充)
endCenter:终点位置(通常和起始点相同,否则会有偏移)
endRadius:终点半径(也就是渐变的扩散长度)
options:绘制方式,DrawsBeforeStartLocation 开始位置之前就进行绘制,到结束位置之后不再绘制,
DrawsAfterEndLocation开始位置之前不进行绘制,到结束点之后继续填充
*/
CGContextDrawRadialGradient(context, gradient, CGPointMake(100,100), 0, CGPointMake(105, 105), 80, CGGradientDrawingOptions.DrawsAfterEndLocation)
}
渐变填充
有时候 我们需要在一个矩形中填充渐变,在此可以利用渐变裁切来完成。
继续在CGViewSix中添加以下方法
/**
绘制了一个矩形填充的渐变
- parameter context: 上下文对象
*/
func drawRectWithLinearGradientFill(context: CGContextRef) {
// 使用rgb颜色空间
/*
CGColorSpaceCreateDeviceRGB() 使用RGB颜色空间
CGColorSpaceCreateDeviceCMYK() 使用CMYK颜色空间
CGColorSpaceCreateDeviceGray() 使用Gray颜色空间
*/
let colorSpace = CGColorSpaceCreateDeviceRGB()
// 裁剪出一块矩形用于显示,注意必须先裁剪再调用渐变
CGContextClipToRect(context, CGRectMake(10, 10, 200, 140))
// 裁切还可以使用UIKit中封装的对应方法
// UIRectClip(self.bounds)
let components: [CGFloat] = [200.0/255.0,50.0/255.0,80.0/255.0,1,
230.0/255.0,127.0/255.0,127.0/255.0,1,
249.0/255.0,200.0/255.0,240.0/255.0,1,
1.0,1.0,1.0,1.0]
let locations = [0.0, 0.4, 0.8, 1.0]
let gradient = CGGradientCreateWithColorComponents(colorSpace, components, components, locations.count)
CGContextDrawLinearGradient(context, gradient, CGPointMake(10, 10), CGPointMake(self.bounds.size.width - 20, self.bounds.size.height - 20), CGGradientDrawingOptions.DrawsAfterEndLocation)
}
叠加模式
使用Quartz 2D绘图时后面绘制的图像会覆盖前面的,默认情况下如果前面的被覆盖后将看不到后面的内容,但是有时候这个结果并不是我们想要的,因此在Quartz 2D中提供了填充模式供开发者配置调整。由于填充模式类别特别多。
因此下面以一个例子来说明:
新建一个CGViewSeven
override func drawRect(rect: CGRect) {
super.drawRect(rect)
let rect0 = CGRectMake(0, 130.0, 320.0, 50.0)
let rect1 = CGRectMake(0, 390.0, 320.0, 50.0)
let rect2=CGRectMake(20, 50.0, 10.0, 250.0)
let rect3=CGRectMake(40.0, 50.0, 10.0, 250.0)
let rect4=CGRectMake(60.0, 50.0, 10.0, 250.0)
let rect5=CGRectMake(80.0, 50.0, 10.0, 250.0)
let rect6=CGRectMake(100.0, 50.0, 10.0, 250.0)
let rect7=CGRectMake(120.0, 50.0, 10.0, 250.0)
let rect8=CGRectMake(140.0, 50.0, 10.0, 250.0)
let rect9=CGRectMake(160.0, 50.0, 10.0, 250.0)
let rect10=CGRectMake(180.0, 50.0, 10.0, 250.0)
let rect11=CGRectMake(200.0, 50.0, 10.0, 250.0)
let rect12=CGRectMake(220.0, 50.0, 10.0, 250.0)
let rect13=CGRectMake(240.0, 50.0, 10.0, 250.0)
let rect14=CGRectMake(260.0, 50.0, 10.0, 250.0)
let rect15=CGRectMake(280.0, 50.0, 10.0, 250.0)
let rect16=CGRectMake(30.0, 310.0, 10.0, 250.0)
let rect17=CGRectMake(50.0, 310.0, 10.0, 250.0)
let rect18=CGRectMake(70.0, 310.0, 10.0, 250.0)
let rect19=CGRectMake(90.0, 310.0, 10.0, 250.0)
let rect20=CGRectMake(110.0, 310.0, 10.0, 250.0)
let rect21=CGRectMake(130.0, 310.0, 10.0, 250.0)
let rect22=CGRectMake(150.0, 310.0, 10.0, 250.0)
let rect23=CGRectMake(170.0, 310.0, 10.0, 250.0)
let rect24=CGRectMake(190.0, 310.0, 10.0, 250.0)
let rect25=CGRectMake(210.0, 310.0, 10.0, 250.0)
let rect26=CGRectMake(230.0, 310.0, 10.0, 250.0)
let rect27=CGRectMake(250.0, 310.0, 10.0, 250.0)
let rect28=CGRectMake(270.0, 310.0, 10.0, 250.0)
let rect29=CGRectMake(290.0, 310.0, 10.0, 250.0)
UIColor.yellowColor().set()
UIRectFill(rect0)
UIColor.greenColor().set()
UIRectFill(rect1)
UIColor.redColor().set()
UIRectFillUsingBlendMode(rect2, CGBlendMode.Clear )
UIRectFillUsingBlendMode(rect3, CGBlendMode.Color )
UIRectFillUsingBlendMode(rect4, CGBlendMode.ColorBurn)
UIRectFillUsingBlendMode(rect5, CGBlendMode.ColorDodge)
UIRectFillUsingBlendMode(rect6, CGBlendMode.Copy)
UIRectFillUsingBlendMode(rect7, CGBlendMode.Darken)
UIRectFillUsingBlendMode(rect8, CGBlendMode.DestinationAtop)
UIRectFillUsingBlendMode(rect9, CGBlendMode.DestinationIn)
UIRectFillUsingBlendMode(rect10, CGBlendMode.DestinationOut)
UIRectFillUsingBlendMode(rect11, CGBlendMode.DestinationOver)
UIRectFillUsingBlendMode(rect12, CGBlendMode.Difference)
UIRectFillUsingBlendMode(rect13, CGBlendMode.Exclusion)
UIRectFillUsingBlendMode(rect14, CGBlendMode.HardLight)
UIRectFillUsingBlendMode(rect15, CGBlendMode.Hue)
UIRectFillUsingBlendMode(rect16, CGBlendMode.Lighten)
UIRectFillUsingBlendMode(rect17, CGBlendMode.Luminosity)
UIRectFillUsingBlendMode(rect18, CGBlendMode.Multiply)
UIRectFillUsingBlendMode(rect19, CGBlendMode.Normal)
UIRectFillUsingBlendMode(rect20, CGBlendMode.Overlay)
UIRectFillUsingBlendMode(rect21, CGBlendMode.PlusDarker)
UIRectFillUsingBlendMode(rect22, CGBlendMode.PlusLighter)
UIRectFillUsingBlendMode(rect23, CGBlendMode.Saturation)
UIRectFillUsingBlendMode(rect24, CGBlendMode.Screen)
UIRectFillUsingBlendMode(rect25, CGBlendMode.SoftLight)
UIRectFillUsingBlendMode(rect26, CGBlendMode.SourceAtop)
UIRectFillUsingBlendMode(rect27, CGBlendMode.SourceIn)
UIRectFillUsingBlendMode(rect28, CGBlendMode.SourceOut)
UIRectFillUsingBlendMode(rect29, CGBlendMode.XOR)
}
添加到一个新的vc中 效果:
对比代码和显示效果查看每种叠加效果
上下文变换
在view中可以利用transform对试图进行平移旋转缩放,绘图中我们也经常用到图形形变,在CoreText中绘制文字的时候因为Core Graphics坐标原点在左下角、UIKit在右上角 。所有要通过变换转过来,下面通过一个图片的变换演示一下图形上下文的形变。
class CGViewEight: UIView {
override func drawRect(rect: CGRect) {
super.drawRect(rect)
let context = UIGraphicsGetCurrentContext()
self.drawImage(context!)
}
/**
平移旋转缩放
- parameter context: 上下文对象
*/
func drawImage(context:CGContextRef){
//保存初始状态
CGContextSaveGState(context)
//形变第一步:图形上下文向右平移100
CGContextTranslateCTM(context,100, 0)
//
// //形变第二步:缩放0.8
CGContextScaleCTM(context, 0.8, 0.8)
//形变第三步:旋转
CGContextRotateCTM(context, CGFloat(M_PI_4)/4)
let img = UIImage(named: "haha")
//从某一点开始绘制
// img?.drawAtPoint(CGPoint(x: 0, y: 100))
//在某个rect里面绘制
img?.drawInRect(self.bounds)
}
}
使用Core Graphics绘制图像
class CGViewNine: UIView {
// 在前面基本绘图部分,绘制图像时使用了UIKit中封装的方法进行了图像绘制,我们不妨看一下使用Quartz 2D内置方法绘制是什么效果。
override func drawRect(rect: CGRect) {
super.drawRect(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
self.drawImage(context)
}
func drawImage(context: CGContextRef) {
let image = UIImage(named: "haha")
let size = UIScreen.mainScreen().bounds.size
CGContextSaveGState(context)
let height: CGFloat = 450.0
let y: CGFloat = 50.0
// 图像绘制
let rect = CGRectMake(10, y, 300, height)
// 在Core Graphics中坐标系的y轴正方向是向上的,坐标原点在屏幕左下角,y轴方向刚好和UIKit中y轴方向相反
CGContextScaleCTM(context, 1.0, -1.0) //在y轴缩放-1相当于沿着x张旋转180
CGContextTranslateCTM(context, 0, -(size.height-(size.height-2*y-height))) //向上平移
CGContextDrawImage(context, rect, image?.CGImage)
}
}
由于坐标问题 我们做了翻转和平移
绘制到位图
利用位图图形上下文给一个图片添加水印,在下面的程序中我们首先创建上下文,然后在上下文中绘制图片、直线和文本,最后从当前位图上下文中取得最终形成的新图片显示到界面。
class ViewControllerFour: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let image = self.drawImageAtImageContext()
let imageView = UIImageView(image: image)
imageView.center=CGPointMake(self.view.bounds.width * 0.5, self.view.bounds.height * 0.5)
self.view.addSubview(imageView)
}
private func drawImageAtImageContext() -> UIImage {
// 获得一个位图图形上下文
let size = self.view.bounds.size
UIGraphicsBeginImageContext(size)
let image = UIImage(named: "haha")
image?.drawInRect(self.view.bounds)
// 添加水印
let str = "测试图片"
let wordSize = (str as NSString).sizeWithAttributes([NSFontAttributeName:UIFont.boldSystemFontOfSize(16),NSForegroundColorAttributeName:UIColor.redColor()])
(str as NSString).drawInRect(CGRectMake(self.view.bounds.size.width - wordSize.width - 10, self.view.bounds.size.height - wordSize.height - 10, wordSize.width, wordSize.height), withAttributes: [NSFontAttributeName:UIFont.boldSystemFontOfSize(16),NSForegroundColorAttributeName:UIColor.redColor()])
//返回绘制的新图形
let newImage = UIGraphicsGetImageFromCurrentImageContext()
//保存图片
// let data = UIImagePNGRepresentation(newImage)
// data?.writeToFile("/Users/admin/Desktop/Gauge/haha.png", atomically: true)
//不要忘记关闭对应上下文
UIGraphicsEndImageContext()
return newImage
}
// 注意:上面这种方式绘制的图像除了可以显示在界面上还可以调用对应方法进行保存(代码注释中已经包含保存方法);除此之外这种方法相比在drawRect:方法中绘制图形效率更高,它不用每次展示时都调用所有图形绘制方法。
}