GCD ディスパッチ キューを使用します。FIFO の順序付けとブロックが自動的に提供されます。すでに実行中の要求をキャンセルすることはできませんが、他の実行を阻止することはできます。
CoreData を使用しているとは言わず、すでに別のスレッドを使用しているため、「データベース」として CoreData を使用していないと仮定します。
次のような簡単なことを試してください...
クラスが初期化されたときにキューを作成します(または、常にそこにあると想定されている場合はアプリが起動します)...
dispatch_queue_t workQ = dispatch_queue_create("label for your queue", 0);
クラスが解放されたとき(または他の適切な時間)に解放します...
dispatch_release(workQ);
キャンセルのようなものを取得するには、別の選択が行われた場合、トークンを使用して、作業中のリクエストが「最新」であるかどうか、またはそれ以降に別のリクエストが来ているかどうかを確認するなど、簡単なことを行うことができます...
static unsigned theWorkToken;
unsigned currentWorkToken = ++theWorkToken;
dispatch_async(workQ, ^{
// Check the current work token at each step, to see if we should abort...
if (currentWorkToken != theWorkToken) return;
MyData *data = queryTheDatabaseForData(someQueryCriteria);
if (currentWorkToken != theWorkToken) return;
[data doTimeConsumingProcessing];
for (Foo *foo in [data foo]) {
if (currentWorkToken != theWorkToken) return;
// Process some foo object
}
// Now, when ready to interact with the UI...
if (currentWorkToken != theWorkToken) return;
dispatch_async(dispatch_get_main_queue(), ^{
// Now you are running in the main thread... do anything you want with the GUI.
});
});
ブロックは、スタック変数「currentWorkToken」とその現在の値を「キャプチャ」します。設定してから変更された場合にのみ、連続カウントを追跡する必要がないため、ここではロック解除チェックで問題ないことに注意してください。最悪の場合、余分な手順を実行します。
CoreData を使用している場合は、NSPrivateQueueConcurrencyType を使用して MOC を作成できます。プライベート MOC には独自の...
static unsigned theWorkToken;
unsigned currentWorkToken = ++theWorkToken;
[managedObjectContext performBlock:^{
// Check the current work token at each step, to see if we should abort...
if (currentWorkToken != theWorkToken) return;
MyData *data = queryTheDatabaseForData(someQueryCriteria);
if (currentWorkToken != theWorkToken) return;
[data doTimeConsumingProcessing];
for (Foo *foo in [data foo]) {
if (currentWorkToken != theWorkToken) return;
// Process some foo object
}
// Now, when ready to interact with the UI...
if (currentWorkToken != theWorkToken) return;
dispatch_async(dispatch_get_main_queue(), ^{
// Now you are running in the main thread... do anything you want with the GUI.
});
}];
GCD/Blocks は、この種のものに適した方法です。
編集
なぜそれが好まれるのですか?まず、ブロックを使用すると、別のクラス (NSOperation) の他のメソッドに広がる代わりに、コードをローカライズしたままにすることができます。他にもたくさんの理由がありますが、個人的な好みについて話しているわけではないので、個人的な理由は脇に置いておきます。私はAppleのことを話していました。
ある週末、WWDC 2011 のすべてのビデオをご覧ください。さあ、それは本当に爆発です。私はそれを心から意味します。あなたがアメリカにいるなら、長い週末が近づいています。もっと良いことを考えられないに違いない...
とにかく、これらのビデオを見て、さまざまなプレゼンターが GCD とブロックの使用を強く推奨すると述べた回数を数えることができるかどうかを確認してください。
さて、WWDC 2012 ですぐにすべてが変わるかもしれませんが、私はそれを疑っています。
具体的には、この場合、NSOperation よりも優れたソリューションでもあります。はい、まだ開始していない NSOperation をキャンセルできます。ウーピー。NSOperation は、既に実行を開始した操作を自動的にキャンセルする方法をまだ提供していません。isCanceled をチェックし続け、キャンセル要求が行われたときに中止する必要があります。そのため、if (currentToken != theWorkToken) はすべて if ([self isCancelled]) のように存在する必要があります。はい、後者の方が読みやすいですが、未処理の操作を明示的にキャンセルする必要もあります。
私にとって、GCD/blocks ソリューションは、従うのがはるかに簡単で、ローカライズされており、(提示されているように) 暗黙的なキャンセル セマンティクスを備えています。NSOperation の唯一の利点は、開始前にキャンセルされた場合、キューに入れられた操作が自動的に実行されなくなることです。ただし、独自の実行中の操作をキャンセルする機能を提供する必要があるため、NSOperation には利点がありません。
NSOperation には適切な場所があり、単純な GDC よりも優先するいくつかの場所をすぐに思いつくことができますが、ほとんどの場合、特にこの場合は適切ではありません。