Cómo usar Bolts Framework

Justo ahora veo este anuncio de Facebook sobre Bolts Framework para iOS.

Puedo ver esto como concepto principal " The first component in Bolts is “tasks”, which make organization of complex asynchronous code more manageable " Pero no obtuve esto. Me confunde sobre el Bolt framework que cómo podría usarlo ( whether it related to webservice or use to parsing JSON response ).

No proporcionaron ningún ejemplo con proyectos xcode. Solo proporcione un ejemplo con ParseObject con parse SDK, pero no con parse SDK.

Facebook proporciona una explicación sobre esto . Pero no puedo saber cómo integrarme con mi proyecto.

El código que proporcionaron es muy confuso.

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

Podemos download tornillos-marco aquí . ¿Alguien podría explicar más sobre esto? Estoy muy ansioso por saber sobre esta nueva tecnología …

Actualización: Aquí recibí una respuesta sobre la nueva pregunta de los tornillos.

Ejemplos: suponga que desea cargar todas las imágenes de AssertLibrary y cambiar el tamaño de todas las imágenes al tamaño estándar mientras se carga, por lo que se activará si se hace con el hilo principal. En este lugar, si va con una operación asíncrona, ¿cómo usar BFTask con él? Otro ex En una ocasión, está intentando llamar a 10 web services en paralelo con una operación asíncrona, ¿cómo puede usar GCD con BFTask?

Bolts es genial. Estoy de acuerdo en que la documentation está un poco desconcertada en este momento. Aquí hay un ejemplo rápido:

 // 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... }]; 

Lo he encontrado especialmente útil para las terminaciones grupales (semi pseudocódigo):

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

Esta es una manera más limpia de hacer lo que de otro modo podría hacer con los grupos de envío. Sin embargo, hay mucho más en cuanto a la secuenciación de sus tareas tanto en serie como en paralelo, etc., etc.

Espero que te ayude a comenzar.

Aquí hay un ejemplo completo de una aplicación que podría admitir a múltiples actores que cambian datos mientras procesan las requestes de networking y la interacción del usuario.

He establecido una guía para mí para usar el BFExecutor vinculado a la serie dispatch_queue_t al tocar cualquier service relacionado con la security de los hilos.

Señalar otras buenas prácticas sería útil, ¡gracias!

 #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 

Los resultados son los esperados. La initialization se intenta con la key = 1, pero se difiere hasta que deja de cambiar. El service se inicializa en su queue con la key = 5 y luego se reinicializa con la tecla = 4.

Resultados:

 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 

Consulte los files de testing (por ejemplo, TaskTests.m) para ver ejemplos. Los ejemplos en Github fueron específicos de Parse.

Generalmente, mirar las testings escritas para un software sería suficiente para aprender a usar el código.