How to use Bolts Framework[Facebook+Parse]

佐手、 提交于 2019-12-03 09:40:31

问题


Just Now I see this announcement from Facebook about Bolts Framework for IOS.

I can see this as main concept:

The first component in Bolts is “tasks”, which make organization of complex asynchronous code more manageable

But I didn't get this. I got confused about Bolts framework. How to use it(whether its related to web service or to JSON response parsing).

They provided examples with ParseObject with parse SDK but I don't know about it and they didn't provide any example with Xcode project.

Facebook provided explanation about this. But I can't figure out how to integrate with my project.

Code they provided is very confusing:

[[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;
}];

We can download bolts-framework here. Can anyone please explain more about this?

Update: Here I received some answer about new question of bolts.

Examples: Assume you want to load all images from AssertLibrary and resize all images to standard size while loading, so it will struck if do with main thread. In this place, If you go with async operation means, How to use BFTask with it? Another Ex. In one time, you are trying to call 10 webservice parallel with async operation, how could you use GCD with BFTask?


回答1:


Bolts is great. Agree that the documentation is a little unfocussed right now. Here's a quick example, though:

// the completion source is the *source* of the task...
BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];
[self asynchronousMethodWithCompletion:^(id response, NSError *error) {
   // your task completed; inform the completion source, which handles
   // the *completion* of the task
   error ? [source setError:error] : [source setResult:entity];
}];

[source.task continueWithBlock:^id(BFTask *task) {
   // this will be executed after the asynchronous task completes...
}];

I've found it especially useful for group completions (semi pseudo-code):

NSMutableArray *tasks = @[].mutableCopy;
loop {
  BFTaskCompletionSource *source = [BFTaskCompletionSource taskCompletionSource];

  // ...make a task similar to above...

  [tasks addObject:source.task];
}

// now the group completion:
BFTask *groupTask = [BFTask taskForCompletionOfAllTasks:tasks.copy];
[source.task continueWithBlock:^id(BFTask *task) {
   // this will be executed after *all* the group tasks have completed
}];

This is a neater way of doing what you might otherwise do with dispatch groups. There's plenty more to it, though, in terms of sequencing your tasks in both serial and parallel, etc. etc.

Hope that helps you get started.




回答2:


Here's a full example of an application that could support multiple actors changing data while processing networking requests and user interaction.

I've set a guideline for myself to use the BFExecutor linked to the serial dispatch_queue_t when touching anything service related for thread safety.

Pointing out other best practices would be useful, thanks!

#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

The results are as expected. Initialization is attempted with the key = 1, but is differed until it stops changing. The service is then initialized on its queue with key = 5 and then re-initialized with key = 4.

Results:

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



回答3:


Refer to the test files (i.e TaskTests.m) for examples. The examples on Github were specific to Parse.

Generally looking at the tests written for a software would be sufficient in learning how to use the code.



来源:https://stackoverflow.com/questions/21521570/how-to-use-bolts-frameworkfacebookparse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!