mamcx
mamcx

Reputation: 16186

Is possible to turn a callback into a async block?

I'm implementing the dropbox api for my new project app. The api is based around delegates & callbacks, in pairs (success + fail) like:

- (void)restClient:(DBRestClient*)client loadedMetadata:(DBMetadata*)metadata;
- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error; 

- (void)restClient:(DBRestClient*)client loadedAccountInfo:(DBAccountInfo*)info;
- (void)restClient:(DBRestClient*)client loadAccountInfoFailedWithError:(NSError*)error; 

I wonder if exist a way to turn that into a obj-c async block, so I could do this:

+ (void)loadMetadata:(DBRestClient *)client queue:(NSOperationQueue *)queue completionHandler:(void (^)(DBMetadata*, NSError*))handler

Exist a kind of pattern that could be used for this? Or is necessary that the library be build with blocks from the start?

Upvotes: 5

Views: 914

Answers (2)

Nate Petersen
Nate Petersen

Reputation: 888

There is now an open source library called 'DropBlocks' that provides block-based versions of all the Dropbox iOS SDK functions.

https://github.com/natep/DropBlocks

Full disclosure: I am the author of this library. I wrote it after becoming frustrated with the delegate paradigm described in this question. Feel free to check out the source to see how I implemented it.

Upvotes: 7

Richard J. Ross III
Richard J. Ross III

Reputation: 55583

You can make a helper function for this:

-(void) loadMetadataOnQueue:(NSOperationQueue *) queue completion:(void (^)(DBMetadata*, NSError*))handler
{
    // assuming this is a category on DBRestClient
    AsyncDelegate *delegate = [AsyncDelegate new];
    delegate.metadataBlock = handler;
    self.delegate = delegate;

    [self loadMetadata:queue];
}

@interface AsyncDelegate

@property(readwrite, copy) void (^metadataBlock)(DBMetadata*, NSError*);

@end

@implementation AsyncDelegate

@synthesize metadataBlock;

-(void)restClient:(DBRestClient*)client loadedMetadata:(DBMetadata*)metadata
{
    metadataBlock(metadata, nil);
}

- (void)restClient:(DBRestClient*)client loadMetadataFailedWithError:(NSError*)error
{
    metadataBlock(nil, error);
}

end

Upvotes: 2

Related Questions