Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I specify the return types in GCD blocks

How can i specify the return types in GCD blocks? Here I want to return my result as NSData ...

- (NSData *)returnData:(NSString *)urlString{
    dispatch_queue_t concurrentQueue = 
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    dispatch_sync(concurrentQueue, ^{   // here return type showing error

        NSString *strUrl = urlString;
        if([strUrl length] == 0)
            return nil; // from this point i want to stop the execution of the block and return nil .

        // otherwise only continue the left operations



    });         
}
like image 215
Sachu Vijay Avatar asked Dec 01 '11 20:12

Sachu Vijay


3 Answers

- (NSData *)returnData:(NSString *)urlString {
    dispatch_queue_t concurrentQueue = 
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // Declare your local data outside the block.
    // `__block` specifies that the variable can be modified from within the block.
    __block NSData *localData = nil;

    dispatch_sync(concurrentQueue, ^{
        // Do something with `localData`...
        localData = somethingWonderful;
    });

    // `localData` now contains your wonderful data.
    return localData;
}

The block's format (parameters/return type) are specified in the function's signature. In this case, dispatch_sync uses a block with no return type and no parameters. If you want further variables to work with you need to declare them outside the block, as in the code above.

like image 76
Stuart Avatar answered Oct 07 '22 02:10

Stuart


Since a block shares the scope with the parent, it's easiest not to specify a return type at all. For example:

- (NSData *)returnData:(NSString *)urlString{
    dispatch_queue_t concurrentQueue = 
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    __block NSData *data; // the __block keyword allows this variable to be changed by a block

    dispatch_sync(concurrentQueue, ^(NSData *)){   // here return type showing error

        data = [NSData dataWithContentsOfURL:@"http://stackoverflow.com"];

    });         

    return data;
}

If you do want to specify a return type, then you cannot use dispatch_sync(), because it only accepts blocks with no return type. An example of how to use blocks manually is:

typedef NSData *(^MyDataBlock)();
MyDataBlock getData = ^ NSData *() {
  return [NSData data];
};

NSData *data = getData();

Note that because you are not using dispatch_sync() in the second example this code will execute immediately on the current queue instead of waiting until there is some available CPU time. Waiting for the CPU have some idle time can actually be faster than executing it immediately.

The advantage is this approach is much more flexible, you can pass the getData variable around to other methods and so on, and they could even execute it inside their own dispatch_sync() call to take advantage of GCD's priority system.

like image 37
Abhi Beckert Avatar answered Oct 07 '22 01:10

Abhi Beckert


What's the exact error you're seeing? Because this line

dispatch_sync(concurrentQueue, ^(NSData *)){   // here return type showing error

has a syntax error. You've got a stray ) after your block argument list.

Even if you fix that, you have another problem, which is that you're trying to return a value from a block passed to dispatch_sync(), and yet dispatch_sync() expects a block that returns void. It seems that what you're really trying to do is return the data from the function, but to do this you need to pass the data from the block back to your outer function. You can do this with a __block-qualified variable, like this:

- (NSData *)returnData:(NSString *)urlString{
    dispatch_queue_t concurrentQueue = 
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    __block NSData *localData = nil;

    dispatch_sync(concurrentQueue, ^{
        if ([urlString length] == 0) {
            // we don't have any data to return
            return; // localData is already nil
        }
        // calculate localData
        localData = ...;
    });
    // Now localData should be populated
    return localData;
}
like image 35
Lily Ballard Avatar answered Oct 07 '22 03:10

Lily Ballard