5

私のUIViewのサブクラスは、サブレイヤーを多用して複雑な画像を作成します。画面上にはこれらのビューが最大30個あり、iPad 2ではperimeterPath(perimeterLayerのパス属性)に沿ったアニメーションのパフォーマンスが低下していました。

元々、ビューのレイヤーにサブレイヤーとして構成レイヤーを追加するだけでした。

[self.layer addSublayer:self.leftsideLayer];  // CAShapeLayer
[self.layer addSublayer:self.rightsideLayer]; // CAShapeLayer
[self.layer addSublayer:self.perimeterLayer]; // CAShapelayer
[self.layer addSublayer:self.valueLayer];     // CAShapeLayer
[self.layer insertSublayer:self.gradientLayer atIndex:0]; // CAGradientLayer + CAShapeLayer (as mask)

画面上のレンダリングは完璧です。しかし、アニメーションが遅れ始めていたので、一時レイヤーをビットマップにレンダリングすることを目的として、一時レイヤーにビルドするためにこのコードを準備しました。ステップ1は、既存のコードを少しやり直すことができるようにすることでした。

CALayer *tmpLayer = [CALayer layer];
[tmpLayer addSublayer:self.leftsideLayer];  // CAShapeLayer
[tmpLayer addSublayer:self.rightsideLayer]; // CAShapeLayer
[tmpLayer addSublayer:self.perimeterLayer]; // CAShapelayer
[tmpLayer addSublayer:self.valueLayer];     // CAShapeLayer
[tmpLayer insertSublayer:self.gradientLayer atIndex:0]; // CAGradientLayer + CAShapeLayer (as mask)
[self.layer addSublayer:tmpLayer];

予想通り、それはうまくいきました。

次のステップは、これらすべてのレイヤーの事前レンダリングされたバージョンを生成することです。

//  [self.layer addSublayer:tmpLayer];
    UIGraphicsBeginImageContextWithOptions([self bounds].size, YES, 0.0);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [self drawLayer:tmpLayer inContext:ctx];
    UIImage *renderedImageOfMyself = UIGraphicsGetImageFromCurrentImageContext();
    if (!renderedImageOfMyself) {
        NSLog(@"Well that didn't work");
    }
    UIGraphicsEndImageContext();
    [self.layer setContents:renderedImageOfMyself.CGImage];

その結果、画面に黒い長方形が表示されたので、次に試してみました。

// [self.layer setContents:renderedImageOfMyself.CGImage];
[self addSubview:[[UIImageView alloc] initWithImage:renderedImageOfMyself]];

それはまた私に黒い長方形を与えているので、私は画面上で黒い長方形を取得するどちらの方法でもうまくいくと結論付けました;-)しかし、私はどういうわけかトップレイヤーをビットマップグラフィックスコンテキストにレンダリングするのを台無しにしました。

新しいコンテキストを開始する際のオプションの部分、YESとNO、1.0と0.0をいじってみました。すべて無駄に。

次のプロセスで何が欠けていますか:

  • 新しいグラフィックコンテキストを開始します
  • そのコンテキストに私のレイヤーを描画します
  • そのコンテキストから画像を取得します

ありがとう!

4

2 に答える 2

10

私がしていなかったことがわかりました:私のレイヤーはそのコンテンツを描画したことがないので、レイヤーから画像を取得しようとする前に setNeedsDisplay をレイヤーに送信する必要がありました( drawLayer:inContext: のようなメソッド名では少し奇妙に思えます:と renderInContext: )

[tmpLayer setNeedsDisplay];
UIGraphicsBeginImageContextWithOptions([self bounds].size, YES, 0.0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[tmpLayer renderInContext:ctx];
renderedImageOfMyself = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.layer setContents:renderedImageOfMyself.CGImage];
于 2012-11-11T06:02:51.930 に答える
2

良い仕事ですが、iOS 6 では奇妙なポインターが機能しないことがあります。

これが将来誰かに役立つことを願っています:)(Todd Yandellによるstackoverflow poweverで見つけたコードの一部)

UIGraphicsBeginImageContextWithOptions([tmpLayer frame].size, YES, 0.0);
[tmpLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
于 2013-04-04T09:23:00.227 に答える