simplificar simplificacion resueltos proposición proposiciones proposicional proporciones metodo lógica logicas logica leyes ejercicios bicondicional algebraico objective-c cocoa objective-c-blocks

objective-c - simplificacion - simplificar en logica proposicional



¿Cómo simplificar la lógica de devolución de llamada con un bloque? (3)

Digamos que necesito comunicarme con una clase que proporciona un protocolo y llama a los métodos de delegado cuando se completa una operación, como sigue:

@protocol SomeObjectDelegate @required - (void)stuffDone:(id)anObject; - (void)stuffFailed; @end @interface SomeObject : NSObject { } @end

Ahora, he decidido que si bien podría hacer que otra clase implemente el método stuffDone: delegate, he decidido que prefiero encapsular el proceso en un bloque que está escrito en algún lugar cercano a donde SomeObject está instanciado, llamado, etc. ¿Cómo podría hacer esto? O en otras palabras, si nos fijamos en this famoso artículo sobre bloques (en la sección Reemplazar devoluciones de llamada); ¿cómo podría escribir un método en SomeObject que acepte un completionHandler: de géneros?


El siguiente enlace explica cómo las llamadas devueltas usando delegados se pueden reemplazar fácilmente con bloques.

Los ejemplos incluyen UITableview, UIAlertview y ModalViewController.

Haz click en mi

Espero que esto ayude.


Parece que desea comunicarse con una clase existente que está diseñada para tomar un objeto delegado. Hay una serie de enfoques, que incluyen:

  1. usar una categoría para agregar variantes basadas en bloques de los métodos apropiados;
  2. usar una clase derivada para agregar las variantes basadas en bloques; y
  3. escribe una clase que implemente el protocolo y llame a tus bloques.

Aquí hay una manera de hacerlo (3). Primero asumamos que su SomeObject es:

@protocol SomeObjectDelegate @required - (void)stuffDone:(id)anObject; - (void)stuffFailed; @end @interface SomeObject : NSObject { } + (void) testCallback:(id<SomeObjectDelegate>)delegate; @end @implementation SomeObject + (void) testCallback:(id<SomeObjectDelegate>)delegate { [delegate stuffDone:[NSNumber numberWithInt:42]]; [delegate stuffFailed]; } @end

así que tenemos alguna manera de probar: tendrás un SomeObject real.

Ahora defina una clase que implemente el protocolo y llame a los bloques proporcionados:

#import "SomeObject.h" typedef void (^StuffDoneBlock)(id anObject); typedef void (^StuffFailedBlock)(); @interface SomeObjectBlockDelegate : NSObject<SomeObjectDelegate> { StuffDoneBlock stuffDoneCallback; StuffFailedBlock stuffFailedCallback; } - (id) initWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail; - (void)dealloc; + (SomeObjectBlockDelegate *) someObjectBlockDelegateWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail; // protocol - (void)stuffDone:(id)anObject; - (void)stuffFailed; @end

Esta clase guarda los bloques que pasa y los llama en respuesta a las devoluciones de llamada del protocolo. La implementación es simple:

@implementation SomeObjectBlockDelegate - (id) initWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail { if (self = [super init]) { // copy blocks onto heap stuffDoneCallback = Block_copy(done); stuffFailedCallback = Block_copy(fail); } return self; } - (void)dealloc { Block_release(stuffDoneCallback); Block_release(stuffFailedCallback); [super dealloc]; } + (SomeObjectBlockDelegate *) someObjectBlockDelegateWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail { return (SomeObjectBlockDelegate *)[[[SomeObjectBlockDelegate alloc] initWithOnDone:done andOnFail:fail] autorelease]; } // protocol - (void)stuffDone:(id)anObject { stuffDoneCallback(anObject); } - (void)stuffFailed { stuffFailedCallback(); } @end

Lo único que debe recordar es Block_copy () los bloques al inicializar y Blockselease () más tarde; esto se debe a que los bloques se asignan en pila y su objeto puede sobrevivir a su creación de marco de pila; Block_copy () crea una copia en el montón.

Ahora puedes hacer que todos los pasos basados ​​en delegados lo bloqueen:

[SomeObject testCallback:[SomeObjectBlockDelegate someObjectBlockDelegateWithOnDone:^(id anObject) { NSLog(@"Done: %@", anObject); } andOnFail:^{ NSLog(@"Failed"); } ] ];

Puede usar esta técnica para envolver bloques para cualquier protocolo.

ARC Addendum

En respuesta al comentario: para hacer que este ARC sea compatible, simplemente elimine las llamadas a Block_copy() dejando las asignaciones directas:

stuffDoneCallback = done; stuffFailedCallback = fail;

y elimine el método dealloc . También puede cambiar Blockcopy para copy , es decir, stuffDoneCallback = [done copy]; , y esto es lo que puede suponer que es necesario al leer la documentación de ARC. Sin embargo, no es como la asignación a una variable fuerte que hace que ARC retenga el valor asignado, y al retener un bloque de pila lo copia al montón. Por lo tanto, el código ARC generado produce los mismos resultados con o sin la copy .


Podrías hacer algo como esto:

typedef void (^AZCallback)(NSError *); AZCallback callback = ^(NSError *error) { if (error == nil) { NSLog(@"succeeded!"); } else { NSLog(@"failed: %@", error); } }; SomeObject *o = [[SomeObject alloc] init]; [o setCallback:callback]; // you *MUST* -copy the block [o doStuff]; ...etc;

Luego dentro de SomeObject , podrías hacer:

if ([self hadError]) { callback([self error]); } else { callback(nil); }