ユーザーが画面に触れて指を動かすことができる拡大鏡アプリを作成しています。指の経路に拡大鏡があります。スクリーンショットを撮って実装し、次のように画像を拡大鏡の画像ビューに割り当てます。
CGSize imageSize = frame.size;
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextScaleCTM(c, scaleFactor, scaleFactor);
CGContextConcatCTM(c, CGAffineTransformMakeTranslation(-frame.Origin.x, -frame.Origin.y));
[self.layer renderInContext:c];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenshot;
問題はself.layer renderInContext
が遅いため、ユーザーが指を動かしているときにスムーズに感じられないことです。他のスレッドでself.layer renderInContext
を実行しようとしましたが、拡大鏡の画像に遅延があったため、拡大鏡の画像が奇妙に見えました。
ビューを画像にレンダリングするより良い方法はありますか? renderInContext:
はGPUを使用しますか?
いいえ。iOS6では、renderInContext:が唯一の方法です。遅いです。 CPUを使用します。
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
view.layer
、アニメーションの最終フレームをキャプチャします。view.presentationLayer
、アニメーションの現在のフレームをキャプチャします。UIView *snapshot = [view snapshotViewAfterScreenUpdates:YES];
contents
は不変です。あなたが効果を適用したい場合は良くありません。[view resizableSnapshotViewFromRect:rect afterScreenUpdates:YES withCapInsets:edgeInsets]
snapshotViewAfterScreenUpdates:
と同じですが、サイズ変更可能なインセットを備えています。 content
も不変です。[view drawViewHierarchyInRect:rect afterScreenUpdates:YES];
renderInContext:
よりも高速です。新しいスナップショットAPIについては、WWDC 2013セッション 226 iOSでのEngaging UIの実装 を参照してください。
それが何らかの助けである場合は、実行中のキャプチャ試行を破棄するコードを次に示します。
これにより、ブロックの実行が一度に1つに抑制され、他は破棄されます。 this SO answer から。
dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_queue_t renderQueue = dispatch_queue_create("com.throttling.queue", NULL);
- (void) capture {
if (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW) == 0) {
dispatch_async(renderQueue, ^{
// capture
dispatch_semaphore_signal(semaphore);
});
}
}
これは何をしているのですか?
DISPATCH_TIME_NOW
は、タイムアウトがなしであることを意味するため、赤色の信号ですぐにゼロ以外を返します。したがって、ifコンテンツは実行されません。