1

私は非同期コールバックが初めてで、さまざまなアドバイスを受けています。非同期コールバックを実行する必要があり、何時間もの調査を行った後でも、ブロックまたは GCD とキューを使用する必要があるかどうかはわかりません。どんなポインタでも大歓迎です。

わかった。だから私が本当に求めていたのは:

「「非同期」コールバックを使用するには、GCD とキューを使用する必要がありますか?」

私が答えから集めているのは、答えはYESだということです。間違いなくGCDブロック内のキュー

私の混乱は、以下のコードのように、必要なのはブロックだけであるという指示が与えられたという事実から生じました。

[UIView animateWithDuration:.4f
                 animations:^{
                     flashView.alpha = 0.f;
                 }
                 completion:^(BOOL finished){
                     [flashView removeFromSuperview];
                 }
 ];

しかし、ここでの回答で私が見ているのは、上記のブロックが「非同期」コールバックを作成するには不十分であることです。代わりに、以下のコードのように、ブロック内でGCDキューを使用する必要があります。

- (void)invokeAsync:(id (^)(void))asyncBlock resultBlock:(void (^)(id))resultBlock errorBlock:(void (^)(id))errorBlock {
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        id result = nil;
        id error = nil;
        @try {
            result = asyncBlock();
        } @catch (NSException *exception) {
            NSLog(@"caught exception: %@", exception);
            error = exception;
        }
        // tell the main thread
        dispatch_async(dispatch_get_main_queue(), ^{
            NSAutoreleasePool *secondaryPool = [[NSAutoreleasePool alloc] init];
            if (error != nil) {
                errorBlock(error);
            } else {
                resultBlock(result);
            }
            [secondaryPool release];
        });
        [pool release];
    });
}
4

2 に答える 2

3

非同期コールバックは、現在のスレッドがステートメントを実行し続け、別のスレッドでのコードの実行を切り離して後で実行するものです。

これを実現するための技術がいくつかあります。この例では、4 つの異なる非同期の方法でパラメーター image (単なる例) を使用してメソッド cacheImage: を呼び出しています。

// 1. NSThread
[NSThread detachNewThreadSelector:@selector(cacheImage:) toTarget:self withObject:image];

// 2. performSelector...
[self performSelectorInBackground:@selector(cacheImage:) withObject:image];

// 3. NSOperationQueue
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(cacheImage:) object:image];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];

// 4. GCD
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [self cacheImage:image];
});

はるかに簡単な方法は、他のオプションを使用して自分で作成する代わりに、使用できるスレッドが既にある GCD を使用することです。

ただし、ブロックはオブジェクトとして実装されるため、実際には GCD なしでブロックを使用できます。たとえば、次のようになります。

// block definition
typedef void (^hello_t)();

// method that uses a block as parameter
-(void) runBlock:(hello_t)hello {
    hello();
}

// asynchronous execution of a block
[NSThread detachNewThreadSelector:@selector(runBlock) toTarget:self withObject:^(){
    NSLog(@"hi");
}];

PS: 多数のオブジェクトを作成し、すぐにメモリを解放したい場合を除き、手動で NSAutoreleasePool を使用する必要はありません。また、@try @catch は Objective-C ではめったに使用されません。

于 2013-10-11T16:21:11.913 に答える
2

ここで混乱する点はありません。GCD にはブロック実行もあります。システムの Unix レベルで操作の非同期実行をサポートする GCD API。

ブロック オブジェクトは、C レベルの構文およびランタイム機能です。これらは標準の C 関数に似ていますが、実行可能コードに加えて、自動 (スタック) またはマネージド (ヒープ) メモリへの変数バインディングも含まれる場合があります。したがって、ブロックは、実行時に動作に影響を与えるために使用できる一連の状態 (データ) を維持できます。

Apple は、グランド セントラル ディスパッチ スレッド アーキテクチャ用のプログラムを簡単に記述できるようにするという明確な目標を持ってブロックを設計しましたが、それはそのアーキテクチャから独立しており、他の言語のクロージャとほぼ同じ方法で使用できます。Apple は、GNU Compiler Collection の独自のブランチと Clang LLVM コンパイラ フロント エンドの両方にブロックを実装しています。ブロックの言語ランタイム ライブラリ サポートも、LLVM プロジェクトの一部として利用できます。

したがって、同じ機能があれば、それらのいずれかを使用できます。

于 2013-10-11T05:07:38.273 に答える