Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 221
mamcx Avatar asked Feb 25 '12 18:02

mamcx


People also ask

Can a callback be async?

Asynchronous callbacks are functions passed to another function that starts executing code in the background. Typically, when the code in the background finishes, the async callback function is called as a way of notifying and passing on data to the callback function that the background task is finished.

Is callback function asynchronous or synchronous?

A callback function executes when an asynchronous operation completes. Here is an example of how a setTimeout function works: function printMe() { console.

How do you turn a callback into a promise?

To convert a callback into a promise, you need to return a promise. You run the code with the callback inside the promise. const readFilePromise = () => { return new Promise((resolve, reject) => { fs. readFile(filePath, options, (err, data) => { // ... }) }) }

Can I use await with a callback?

js applications. Async functions return a Promise by default, so you can rewrite any callback based function to use Promises, then await their resolution.


2 Answers

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.

like image 56
Nate Petersen Avatar answered Nov 11 '22 19:11

Nate Petersen


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
like image 21
Richard J. Ross III Avatar answered Nov 11 '22 17:11

Richard J. Ross III