Je jouais avec les chemins de dessin et j'ai remarqué qu'au moins dans certains cas, UIBezierPath surpasse ce que je pensais être un équivalent Core Graphics. La -drawRect:
méthode ci-dessous crée deux chemins: un UIBezierPath et un CGPath. Les chemins sont identiques à l'exception de leurs emplacements, mais caresser le CGPath prend environ deux fois plus de temps que caresser le 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];
}
Les deux chemins utilisent CGContextStrokePath (), j'ai donc créé des méthodes séparées pour tracer chaque chemin afin que je puisse voir l'heure utilisée par chaque chemin dans Instruments. Voici les résultats typiques (arbre d'appel inversé); vous pouvez voir que cela -strokeContext:
prend 9,5 secondes, alors que cela -strokeUIBezierPath:
ne prend que 5 secondes:
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:]
Il semble qu'UIBezierPath optimise en quelque sorte le chemin qu'il crée, ou que je crée le CGPath de manière naïve. Que puis-je faire pour accélérer mon dessin CGPath?
UIBezierPath
est une enveloppe autourCGPathRef
. Que faire si vous exécutez les deux, disons dix millions de fois, puis prenez la moyenne, mais n'utilisez pas d'instruments mais deuxNSDate
objets avant et après les opérations.-drawRect:
est appelé quelques dizaines de fois ou quelques centaines. Je l'ai essayé avec jusqu'à 80000 segments de courbe sur le simulateur (beaucoup trop pour l'appareil). Les résultats sont toujours à peu près les mêmes: CGPath prend environ deux fois plus de temps que UIBezierPath, même si les deux utilisent CGContextStrokePath () pour dessiner. Il semble clair que le chemin construit par UIBezierPath est en quelque sorte plus efficace que celui que je crée avec CGPathAddCurveToPoint (). J'aimerais savoir comment construire des chemins efficaces comme le fait UIBezierPath.Réponses:
Vous avez raison en ce sens qu'il
UIBezierPath
s'agit simplement d'un wrapper objectif-c pour Core Graphics, et donc de performances comparables. La différence (et la raison de votre delta de performances) est que votreCGContext
état lorsque vousCGPath
dessinez directement est assez différent de cette configuration parUIBezierPath
. Si vous regardezUIBezierPath
, il a des paramètres pour:lineWidth
,lineJoinStyle
,lineCapStyle
,miterLimit
etflatness
Lors de l'examen de l'appel (désassemblage) à
[path stroke]
, vous remarquerez qu'il configure le contexte graphique actuel en fonction de ces valeurs précédentes avant d'exécuter l'CGContextStrokePath
appel. Si vous faites la même chose avant de dessiner votre CGPath, il effectuera la même chose:Instantané des instruments:
la source