그리기 경로를 가지고 놀았는데, 적어도 어떤 경우에는 UIBezierPath가 Core Graphics와 동등하다고 생각했던 것보다 성능이 뛰어납니다. -drawRect:
하나 UIBezierPath, 하나 CGPath : 방법에 대하여 두 가지의 경로를 생성한다. 경로는 위치를 제외하고 동일하지만 CGPath를 입력하는 데 UIBezierPath를 입력하는 것보다 약 두 배가 걸립니다.
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Create the two paths, cgpath and uipath.
CGMutablePathRef cgpath = CGPathCreateMutable();
CGPathMoveToPoint(cgpath, NULL, 0, 100);
UIBezierPath *uipath = [[UIBezierPath alloc] init];
[uipath moveToPoint:CGPointMake(0, 200)];
// Add 200 curve segments to each path.
int iterations = 200;
CGFloat cgBaseline = 100;
CGFloat uiBaseline = 200;
CGFloat xincrement = self.bounds.size.width / iterations;
for (CGFloat x1 = 0, x2 = xincrement;
x2 < self.bounds.size.width;
x1 = x2, x2 += xincrement)
{
CGPathAddCurveToPoint(cgpath, NULL, x1, cgBaseline-50, x2, cgBaseline+50, x2, cgBaseline);
[uipath addCurveToPoint:CGPointMake(x2, uiBaseline)
controlPoint1:CGPointMake(x1, uiBaseline-50)
controlPoint2:CGPointMake(x2, uiBaseline+50)];
}
[[UIColor blackColor] setStroke];
CGContextAddPath(ctx, cgpath);
// Stroke each path.
[self strokeContext:ctx];
[self strokeUIBezierPath:uipath];
[uipath release];
CGPathRelease(cgpath);
}
- (void)strokeContext:(CGContextRef)context
{
CGContextStrokePath(context);
}
- (void)strokeUIBezierPath:(UIBezierPath*)path
{
[path stroke];
}
두 경로 모두 CGContextStrokePath ()를 사용하므로 Instruments의 각 경로에서 사용되는 시간을 볼 수 있도록 각 경로를 스트로크하는 별도의 메서드를 만들었습니다. 다음은 일반적인 결과입니다 (호출 트리 반전). 당신은이 볼 수있는 -strokeContext:
9.5 초 걸린다., 동안 -strokeUIBezierPath:
5 초 걸립니다 :
Running (Self) Symbol Name
14638.0ms 88.2% CGContextStrokePath
9587.0ms 57.8% -[QuartzTestView strokeContext:]
5051.0ms 30.4% -[UIBezierPath stroke]
5051.0ms 30.4% -[QuartzTestView strokeUIBezierPath:]
UIBezierPath가 생성하는 경로를 어떻게 든 최적화하는 것처럼 보이거나 순진한 방식으로 CGPath를 생성하고 있습니다. CGPath 그리기 속도를 높이려면 어떻게해야합니까?
답변
UIBezierPath
Core Graphics에 대한 단순히 Objective-c 래퍼라는 점에서 정확 하므로 성능이 비슷합니다. 차이점 (및 성능 델타 이유)은 직접 CGContext
그릴 때 의 상태 CGPath
가 UIBezierPath
. 을 보면 다음에 UIBezierPath
대한 설정이 있습니다.
lineWidth
,lineJoinStyle
,lineCapStyle
,miterLimit
과flatness
에 대한 호출 (디 어셈블리)을 검사 할 때 호출 [path stroke]
을 수행하기 전에 이전 값을 기반으로 현재 그래픽 컨텍스트를 구성한다는 것을 알 수 있습니다 CGContextStrokePath
. CGPath를 그리기 전에 동일한 작업을 수행하면 동일한 작업이 수행됩니다.
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
// Create the two paths, cgpath and uipath.
CGMutablePathRef cgpath = CGPathCreateMutable();
CGPathMoveToPoint(cgpath, NULL, 0, 100);
UIBezierPath *uipath = [[UIBezierPath alloc] init];
[uipath moveToPoint:CGPointMake(0, 200)];
// Add 200 curve segments to each path.
int iterations = 80000;
CGFloat cgBaseline = 100;
CGFloat uiBaseline = 200;
CGFloat xincrement = self.bounds.size.width / iterations;
for (CGFloat x1 = 0, x2 = xincrement;
x2 < self.bounds.size.width;
x1 = x2, x2 += xincrement)
{
CGPathAddCurveToPoint(cgpath, NULL, x1, cgBaseline-50, x2, cgBaseline+50, x2, cgBaseline);
[uipath addCurveToPoint:CGPointMake(x2, uiBaseline)
controlPoint1:CGPointMake(x1, uiBaseline-50)
controlPoint2:CGPointMake(x2, uiBaseline+50)];
}
[[UIColor blackColor] setStroke];
CGContextAddPath(ctx, cgpath);
// Stroke each path
CGContextSaveGState(ctx); {
// configure context the same as uipath
CGContextSetLineWidth(ctx, uipath.lineWidth);
CGContextSetLineJoin(ctx, uipath.lineJoinStyle);
CGContextSetLineCap(ctx, uipath.lineCapStyle);
CGContextSetMiterLimit(ctx, uipath.miterLimit);
CGContextSetFlatness(ctx, uipath.flatness);
[self strokeContext:ctx];
CGContextRestoreGState(ctx);
}
[self strokeUIBezierPath:uipath];
[uipath release];
CGPathRelease(cgpath);
}
- (void)strokeContext:(CGContextRef)context
{
CGContextStrokePath(context);
}
- (void)strokeUIBezierPath:(UIBezierPath*)path
{
[path stroke];
}
악기의 스냅 샷 :