How to create a wrapper to use blocks for a class that uses callbacks?

I immerse myself in iOS programming, and I learn how to use blocks. I have a juicy, redesigned library that I use in my project and it uses one callback method to handle all data requests ...

@protocol SuckyClassDelegate <NSObject> -(void)returnedSuckyData:(NSMutableDictionary*)data; @end @interface SuckyClass: NSObject @property (nonatomic, weak) id<SuckyClassDelegate> delegate; -(void)getSuckyData; @end @interface MyViewController: UIViewController <SuckyClassDelegate> -(void)requestDataFromSuckyClass; @end 

I would like to create a wrapper class for SuckyClass that allows me to use blocks when I need to access data from SuckyClass, but I don't know how to do it. I would like to have something like this ...

 @interface SuckyClassWrapper - (void)requestDataWithSuccessBlock:(void(^)((NSMutableDictionary*)data))successBlock; @end @implementation MyViewController -(void)requestDataFromSuckyClass { SuckyClassWrapper *wrapper = [[SuckyClassWrapper alloc] init]; [wrapper requestDataWithSuccessBlock:^(NSMutableDictionary *data) { NSLog(@"%@", data); } } @end 

... but I can't figure out how to convert the callback process to blocks. Can you somehow give me some direction here?

Thank you for your wisdom!

By the way, I just hacked the code without testing it, so I apologize if there are typos.

+4
source share
2 answers

The trick is to copy the completion block into the iVar class, which can then be called later.

 @property (nonatomic, copy) void (^errorHandler)(NSError *); @property (nonatomic, copy) void (^successHandler)(NSString *); 

Here is a method that saves two blocks for later use, and then calls another class method:

 - (void)methodWithErrorHandler:(void(^)(NSError *error))errorBlock successHandler: (void(^)(NSString *data))successBlock { // Copy the blocks to use later self.successHandler = successBlock; self.errorHandler = errorBlock; // Run code [self doOtherThings]; } 

Later - when what we want to do is completed, we have another method that we call to start the blocks. In this silly code example, we check to see if the class property self.error nil . If it is not nil , we send this error to our saved error block. If it is nil , we pass self.data to the success block.

 - (void)finishThingsUp { // Check to see if we should call the error block or the success block if (self.error) { self.errorHandler(self.error); } else { self.successHandler(self.data); } // Clean up the blocks self.errorHandler = nil; self.successHandler = nil; } 
+5
source

We could use it like this:

 typedef void (^SuccessDataBlock)(NSMutableDictionary *); @interface SuckyClassWrapper : NSObject <SuckyClassDelegate> @property (nonatomic, retain) NSData *inputData; @property (nonatomic, copy) SuccessDataBlock completionHandler; + (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler; @end @implementation SuckyClassWrapper @synthesize inputData; @synthesize completionHandler; - (id)initWithData:(NSData *)data completionHandler:(SuccessDataBlock)handler { self = [super init]; if (self != nil) { inputData = [data retain]; self.completionHandler = handler; } return self; } + (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler { return [[[self alloc] initWithData:data completionHandler:handler] autorelease]; } //implement SuckyClass delegate - (void)returnedSuckyData:(NSMutableDictionary *)data { self.completionHandler(data); } @end 

Using:

 SuckyClassWrapper *wrapper = [SuckyClassWrapper requestData:data successBlock:^(NSMutableDictionary *successData) { //your code here }]; 
+3
source

All Articles