2012-06-07 3 views
9

UIKit Function ReferenceUIGraphicsBeginImageContextWithOptionsによると、私はちょっとだけUIGraphicsBeginImageContextWithOptionsとスレッドについて混乱しています。呼び出されると、ビットマップベースのコンテキストが作成されます。CoreGraphicsの関数またはdrawInRect:の場合はUIImage-drawInRect:withFont:の場合はNSStringのように操作できます。 CoreGraphicsの描画ではすべてが明確です。すべての関数に操作されているCGContextRef引数を渡しますが、UIKit描画メソッドはスタック内の現在のコンテキストを使用します。 What's New in iOS 4.0のリリースノートでは、UIKitのグラフィックスコンテキストに描画UIGraphicsBeginImageContextWithOptionsWithOptionsWithOptionsとマルチスレッド

は今、スレッドセーフであると書かれています。具体的には
グラフィックスにアクセスして操作するためのルーチン
コンテキストは異なる スレッドに存在するコンテキストを正しく処理できるようになりました。
- 文字列とイメージの描画がスレッドセーフです。
- 複数のスレッドにカラーオブジェクトと フォントオブジェクトを使用することは、今や安全です。

これまでのところとても良いです。興味深いのは、私が集中的な図面を作成し、UIGraphicsBeginImageContextWithOptionsでコンテキストを作成して複数の画像を作成するプロジェクトがあることです。しかし、これらの操作に時間がかかり、バックグラウンドスレッドで描画を移動したばかりで、いくつかのアニメーションでそれらを画面に表示すると、すべて正常に動作します。クラッシュやリークはありません。画像は期待通りに描画され、UIGraphicsBeginImageContextWithOptionsはバックグラウンドスレッドのコンテキストを作成しているようですが、すべて正常であるようです。
私の質問は次のとおりです:
- バックグラウンドで正常に動作しているように見えるので、メインスレッドでUIGraphicsBeginImageContextWithOptionsを呼び出す必要があるのはなぜですか?
- メソッドを使用して、現在のコンテキストがないバックグラウンドスレッドなどで、UIGraphicsBeginImageContextWithOptionsを呼び出すことができないため、作成できないようです。
- UIKitのメソッドを使用した背景画像操作の正しいアプローチは何ですか(私はCGBitmapContextCreateを使用することもできますが、作成したコンテキストをコンテキストスタックにプッシュすることも、自分自身で行うこともできません)-drawInRect:メソッドUIImage)?

答えて

21

したがって、数日間の調査の後、UIKitコンテキストを操作するのはスレッドセーフですが、UIGraphicsBeginImageContextWithOptionsが呼び出される必要があるため、メイン以外のスレッドでスレッドを作成することはできないようです「メインスレッドだけで」、それでもやっても問題ないですが、いくつかの小規模な記事を読んで、Appleの開発者フォーラムで他の人と話し合ったところでは、ドキュメントにはUIGraphicsBeginImageContextWithOptionsUIGraphicsPushContextUIGraphicsPopContextはWRONGであり、これらのメソッドを呼び出すことができ、問題なく別のスレッドでコンテキストを使用できます。だから、UIGraphicsBeginImageContextWithOptionsUIGraphicsPushContextUIGraphicsPopContextスレッドセーフです。

+3

...見て、私の質問に答えました。これは、iOS5 SDK以前のドキュメントエラーです(WWDC 2012ビデオにアクセスしている場合は、セッション211とiOS6 SDKドキュメントをチェックしてください)。 –

+0

また、UIGraphicsEndImageContext()を呼び出すことが非常に重要です。または、CPUでうんざりするようなことが始まります。 – bentford

+2

ドキュメントは修正されました: 'iOS 4以降では、あなたのアプリのスレッドからこの関数を呼び出すことができます。 – graver

0

部分的な答え:UIGraphicsPushContextを使用して、独自のCGコンテキストを「UIKitコンテキスト」スタックの先頭にプッシュしてください。そのスレッドからのすべてが(Appleのドキュメントを解釈すると)ペイントされます。 UIGraphicsPopContextを使用してUIKitコンテキストスタックからポップすることを忘れないでください。

これはすべてのUIKit描画操作に適用されます。あなたが尋ねたように、図面UIImageを入力してください。コンテキストをプッシュし、描画してコンテキストをポップします。

+0

これは私の考えですが、残念ながらドキュメントには「UIGraphicsPushContextとUIGraphicsPopContextの両方のアプリケーションのメインスレッドからこの関数を呼び出すべきです」と書かれています – graver

+2

私と私それを見つけることができませんが、私は2011年または2010年のWWDCビデオでこれらの事柄を詳しく説明しました。私が覚えていることから私の直感は、ドキュメンテーションの一部が微妙に誤解を招き、すべてがうまくいくあなただけのビデオからいくつかのルールに従うならば。 (私はあなたがこのアドバイスで農場に賭けるとは思っていませんが、あなたがビデオを見つけたらそれはあなたの質問に答えてくれると思います) – Jesper

+0

私は今見て、答えを書き留めます。 – graver