9

ちょうど今、iOS 用のBolts Frameworkに関するFacebook からのこのアナウンスを目にしました。

これを主なコンセプトとして見ることができます:

Bolts の最初のコンポーネントは、複雑な非同期コードの編成をより管理しやすくする「タスク」です。

しかし、私はこれを取得しませんでした。について混乱しましBolts frameworkた。使い方( whether its related to web service or to JSON response parsing)。

彼らはParseObjectパースSDKで例を提供しましたが、私はそれについて知りません.Xcodeプロジェクトで例を提供しませんでした.

Facebookはこれについて説明を提供しました。しかし、プロジェクトと統合する方法がわかりません。

彼らが提供したコードは非常に紛らわしいです:

[[object saveAsync:obj] continueWithBlock:^id(BFTask *task) {
  if (task.isCancelled) {
    // the save was cancelled.
  } else if (task.error) {
    // the save failed.
  } else {
    // the object was saved successfully.
    SaveResult *saveResult = task.result;
  }
  return nil;
}];

ボルトフレームワークはこちらからダウンロードできます。誰でもこれについてもっと説明できますか?

更新: ここで、ボルトの新しい質問についていくつかの回答を受け取りました。

例: AssertLibrary からすべての画像を読み込み、読み込み中にすべての画像のサイズを標準サイズに変更したい場合、メイン スレッドで実行すると問題が発生します。ここで, 非同期操作で行くとすれば, BFTask をどう使うか? 別の例。一度に、非同期操作で 10 個の Web サービスを並行して呼び出そうとしていますが、どのように BFTask で GCD を使用できますか?

4

3 に答える 3

0

ネットワーク リクエストとユーザー インタラクションの処理中にデータを変更する複数のアクターをサポートできるアプリケーションの完全な例を次に示します。

スレッドセーフに関連するサービスに触れるときは、シリアルdispatch_queue_tにリンクされたBFExecutorを使用するというガイドラインを自分自身に設定しました。

他のベストプラクティスを指摘することは役に立ちます、ありがとう!

#import <Bolts/Bolts.h>

dispatch_queue_t serialQueue;
BFExecutor *serialExecutor;
BFTask *maintask;
int32_t key = 0;
BOOL initialized = FALSE;

@implementation yAppDelegate

- (void)setKey:(int32_t)key_ {
    // Don't worry about success, just appending to outstanding tasks
    maintask = [maintask continueWithExecutor:serialExecutor withBlock:^id(BFTask *task) {
        BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];

        key = key_;
        NSLog(@"set key to %d", key);
        [source setResult:nil];

        if (initialized) {
            [self initialize];
        }

        return source.task;
    }];
}

- (BFTask *)downloadConfig {
    BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];
    dispatch_async(serialQueue, ^{
        NSLog(@"working on init config, key = %d...", key);

        // Trigger from a different queue
        double delayInSeconds = 1.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [source setResult:nil];
        });
    });
    return source.task;
}

- (BFTask *)initializeService {
    BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];
    dispatch_async(serialQueue, ^{
        NSLog(@"working on init service, key = %d...", key);

        // Trigger from a different queue
        double delayInSeconds = 1.0;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            [source setResult:nil];
        });

        // Set final state
        initialized = TRUE;
    });
    return source.task;
}

- (void)initialize {
    int32_t oldKey = key;
    __block bool reinit = false;

    // Start by chaining it to whatever task is in flight without regard to success
    // Everything should use the serialQueue or serialExecutor for thread safety
    maintask = [[[maintask continueWithExecutor:serialExecutor withBlock:^id(BFTask *task) {
        if (oldKey != key) {
            NSLog(@"key out of date (%d != %d).  reinitializing...", oldKey, key);
            reinit = true;
            return [BFTask cancelledTask];
        }
        return [self downloadConfig];
    }] continueWithExecutor:serialExecutor withSuccessBlock:^id(BFTask *task) {
        if (oldKey != key) {
            NSLog(@"key out of date (%d != %d).  reinitializing...", oldKey, key);
            reinit = true;
            return [BFTask cancelledTask];
        }
        return [self initializeService];
    }] continueWithExecutor:serialExecutor withBlock:^id(BFTask *task) {
        if (oldKey != key) {
            NSLog(@"key out of date (%d != %d).  reinitializing...", oldKey, key);
            reinit = true;
        }

        if (task.error || task.exception || task.isCancelled) {
            if (reinit) {
                [self initialize];
            }
            return nil;
        } else {
            NSLog(@"initService completed = %d", key);
            return nil;
        }
    }];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    serialQueue = dispatch_queue_create("serial", NULL);
    serialExecutor = [BFExecutor executorWithDispatchQueue:serialQueue];

    // Start with an empty task so all tasks can be strung together without need to initialize
    maintask = [BFTask taskWithResult:nil];

    // Everything related to changing service state should be contained with the serialQueue dispatch queue
    [self setKey:1];
    [self initialize];
    [self setKey:2];
    [self setKey:3];

    dispatch_async(dispatch_get_main_queue(), ^(void){
        [self setKey:4];
    });

    dispatch_async(serialQueue, ^(void){
        [self setKey:5];
    });

    [self setKey:6];

    // Override point for customization after application launch.
    return YES;
}

@end

結果は予想通りです。key=1 で初期化を試みますが、変化しなくなるまで違います。その後、サービスはキー = 5 でキュー上で初期化され、キー = 4 で再初期化されます。

結果:

set key to 1
key out of date (0 != 1).  reinitializing...
key out of date (0 != 1).  reinitializing...
set key to 2
set key to 3
set key to 6
set key to 5
key out of date (1 != 5).  reinitializing...
key out of date (1 != 5).  reinitializing...
working on init config, key = 5...
working on init service, key = 5...
initService completed = 5
set key to 4
working on init config, key = 4...
working on init service, key = 4...
initService completed = 4
于 2014-04-08T21:47:50.607 に答える
0

例については、テスト ファイル (つまり、TaskTests.m) を参照してください。Github の例は、Parse に固有のものです。

一般に、ソフトウェア用に書かれたテストを見るだけで、コードの使い方を学ぶことができます。

于 2015-09-19T01:26:04.040 に答える