[解決済み] なぜUIBezierPathはCore Graphicsパスより高速なのですか?
質問
私はパスの描画で遊んでいて、少なくともいくつかのケースで、UIBezierPath が Core Graphics の同等品と思われるものより優れていることに気づきました。その
-drawRect:
メソッドは、UIBezierPath と CGPath の 2 つのパスを作成します。これらのパスは位置以外は同じですが、CGPath をストロークすると、UIBezierPath をストロークするよりも約 2 倍の時間がかかります。
- (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];
}
インストゥルメントからのスナップショット。
関連
-
[解決済み] UIPageControlのページネーションドットの色を変更するにはどうしたらよいですか?
-
[解決済み] CGFloatとfloatを使うことの違いは何ですか?
-
[解決済み] iOS UITableViewのHeaderView(セクションヘッダーではない)を追加する
-
[解決済み] iPhoneでMonoTouchは禁止になったのか?[クローズド]
-
[解決済み] 静的ライブラリのObjective-Cカテゴリ
-
[解決済み] drawRectを使うか使わないか(drawRect/Core Graphicsとsubview/imagesをいつ使うか、なぜ使うか)?
-
[解決済み] テーブルビューの行をプログラムで選択する
-
[解決済み] iOSアプリをクラッシュさせる確実な方法とは?
-
[解決済み] CALayerのanchorPointを変更すると、ビューが移動します。
-
[解決済み] UILabelがラベルサイズに合うようにテキストを自動縮小しない
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] UIPageControlのページネーションドットの色を変更するにはどうしたらよいですか?
-
[解決済み] iOSでHTMLをNSAttributedStringに変換する
-
[解決済み] レビュー待ちの状態でバイナリを拒否する(バイナリ拒否ボタンが見つからない)
-
[解決済み] Push Notificationのアラートテキストは何文字まで可能ですか?
-
[解決済み] Xcodeは私のiOSデバイスを見ませんが、iTunesは見ます。
-
[解決済み] Objective-Cのプロトコルでプロパティを含むものはどう扱えばいいのか?
-
[解決済み] 円形のカスタムUIViewの描き方 - iPhoneアプリ
-
[解決済み] カメラロールに画像を保存する方法を教えてください。
-
[解決済み] アプリを提出する前にitunesのリンクを取得する
-
[解決済み] MKMapViewのズームレベル設定