0

私はiOSとObjective-Cにかなり慣れていません。

複雑な(または「複合」)操作の構成を可能な限り簡単にすることを目的としたプロジェクトを開発しています:https ://github.com/stanislaw/SACompositeOperations

そこには4種類の操作があります。2つの単一操作(同期と非同期)と2つの複雑な操作(カスケードと「トランザクション」)です。単一の操作は複雑な操作の「アトム」として使用されるため、Objective-Cのベストプラクティスに従って可能な限り優れたものにしたいと考えています。

私が興味を持っているのは、これらの単一の操作に対してどのコードを選択する必要があるかということです。

2つの単一操作の最初の「同期」を呼び出すとは、おそらく完了ハンドラーと非同期で何かを実行し、完了するまでフローをロックすることを意味します。「非同期」とは、真の非同期操作を意味します。操作ブロックを非同期で実行するだけです。

これが私が現在使用している単一の操作コードです:

同期操作

- (void)run:(syncOperationBlock)block {
    self.semaphore = dispatch_semaphore_create(0);

    block(self);

    while (dispatch_semaphore_wait(self.semaphore, DISPATCH_TIME_NOW))
        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                                       beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]];
}

- (void)finish {
    dispatch_semaphore_signal(self.semaphore);
}

@end

非同期操作

- (void)run:(asyncOperationBlock)block {
    dispatch_queue_t queue = dispatch_queue_create("async_operation.queue", 0);

    dispatch_async(queue, ^{
        block(self);
    });
}

誰かがこれらの単一の同期および非同期操作の解決策を提案できれば、私は感謝します:より一般的で、より一般的で、私が説明したケースにちょうど良い

簡単に言うと、強制同期操作、非同期操作に最適なコードは何ですか?

ありがとう。

4

1 に答える 1

0

この質問をして以来、私のプロジェクトは大幅に進化しました。

構造的な観点から、非同期操作についてはあまり興味深いとは言えません。私のプロジェクトでは、それらはすべてdispatch_asyncに基づいており、最も価値のある機能は、ブロックを集中的に使用して実装されています(主に、実行するブロックに操作自体を譲ります)。 、これらの操作のフローを制御できます)。

ここで注意すべきさらに興味深い点は、同期(または「強制同期」)操作に現在使用しているコードです。実際のアプリでは使用を避ける必要がありますが、単体テストでは引き続き適用できます。1つの例は、まっすぐにする必要があることです。単体テストケースのコンテキストで、その結果をインプレースでテストするための非同期ネットリクエストのカーリー非同期フロー。

私はこれを非特定の質問への回答として投稿していますが、SASyncOperationが強制同期操作に十分であるかどうか(この質問で説明した意味で)についての信頼できる回答を見たいと思います。多分それはもっと改善されるかもしれません。

現在記述されているSASyncOperation

  • メインスレッドで実行されている場合、メインスレッドをブロックしません。
  • while(!completed){}を使用した単純なアプローチのように、過剰なCPUポーリングを生成しません。行う。

これは、コードの最も重要な部分です。

#import "SASyncOperation.h"

@interface SASyncOperation () {
    BOOL _isOnMainThread;
    dispatch_semaphore_t _semaphore;
}
@end

@implementation SASyncOperation

// …

- (void)start {
    _semaphore = dispatch_semaphore_create(0);

    _operation(self);

    if (_finished) return;

    if ((_isOnMainThread = [NSThread isMainThread])) {
        while (dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_NOW)) {
            CFRunLoopRunInMode(kCFRunLoopDefaultMode, [[NSDate distantFuture] timeIntervalSinceNow], NO);
        }
    } else {
        dispatch_semaphore_wait(_semaphore, DISPATCH_TIME_FOREVER);
    }

    _finished = YES;
}

- (void)run:(^(void)(SASyncOperation *)block {
    _operation = [block copy];

    [self start];
}

- (void)finish {
    _finished = YES;

    dispatch_semaphore_signal(_semaphore);

    if (_isOnMainThread) {
        dispatch_async(dispatch_get_main_queue(), ^{
            CFRunLoopStop(CFRunLoopGetMain());
        });
    }
}

// …
@end

SASyncOperationの使用方法は次のとおりです。

SASyncOperation *syncOperation = [[SASyncOperation alloc] init];

[syncOperation run:^(SASyncOperation *so) {
    doSomeThingMultiQueuedPossiblyMultiblockedAndAsynchronous(^{
        soOver = YES;
        [so finish];
    });
}]; // <- (*)

// (*) The flow will be stopped at this point waiting when 'so' operation will finish itself
于 2013-01-11T04:08:12.933 に答える