Как я могу указать типы возврата в блоках GCD - PullRequest
6 голосов
/ 02 декабря 2011

Как я могу указать типы возврата в блоках GCD?Здесь я хочу вернуть свой результат как 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



    });         
}

Ответы [ 4 ]

8 голосов
/ 02 декабря 2011
- (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;
}

Формат блока (параметры / тип возврата) указывается в сигнатуре функции. В этом случае dispatch_sync использует блок без типа возврата и параметров. Если вы хотите, чтобы другие переменные работали с вами, вам нужно объявить их вне блока, как в коде выше.

4 голосов
/ 02 декабря 2011

Поскольку блок разделяет область видимости с родителем, проще всего вообще не указывать тип возвращаемого значения.Например:

- (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;
}

Если вы хотите указать тип возврата, вы не можете использовать dispatch_sync(), поскольку он принимает только блоки без типа возврата.Пример использования блоков вручную:

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

NSData *data = getData();

Обратите внимание, что, поскольку вы не используете dispatch_sync() во втором примере, этот код будет выполнять немедленно в текущей очереди вместоожидание, пока не появится некоторое доступное время процессора.Ожидание того, что у ЦП есть какое-то время простоя, на самом деле может быть быстрее, чем его немедленное выполнение.

Преимущество в том, что этот подход гораздо более гибкий, вы можете передавать переменную getData другим методам и т. Д.они могли бы даже выполнить его в своем собственном вызове dispatch_sync(), чтобы воспользоваться системой приоритетов GCD.

1 голос
/ 02 декабря 2011

Какую именно ошибку вы видите?Поскольку эта строка

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

имеет синтаксическую ошибку.У вас есть блуждающий ) после списка аргументов блока.

Даже если вы исправите это, у вас есть другая проблема: вы пытаетесь вернуть значение из блока, переданного в dispatch_sync() и все же dispatch_sync() ожидает блок, который возвращает void.Кажется, что вы действительно пытаетесь сделать это вернуть данные из функции, но для этого вам нужно передать данные из блока обратно во внешнюю функцию.Вы можете сделать это с помощью __block -квалифицированной переменной, например:

- (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;
}
0 голосов
/ 02 декабря 2011

Чтобы расширить предостережение Frioze: если вы вызываете какой-либо API, не рекомендуемый для использования в главном потоке в очереди, к которой вы _sync, и вы вызываете dispatch_sync из основного потока, вы, возможно, также вызвали этот API из основного потока как вы попросили дождаться его завершения. Это верно не только для блока в вашем вызове _sync, но и для любых предыдущих блоков, отправленных через _async, которые еще не завершены.

...