Как передать блок типа dispatch_block_t в метод - PullRequest
0 голосов
/ 03 ноября 2019

В приведенном ниже коде я пытаюсь передать блок типа dispatch_block_t в dispatch_async, как показано ниже. Я попробовал следующее

        dispatch_async(defaultPriority, block1(2, 3000));
    dispatch_async(defaultPriority, (^block1)(2, 3000));
    dispatch_async(defaultPriority, ^(block1)(2, 3000));

Однако код не компилируется из-за сгенерированной ошибки из-за того, как блок передается методу dispatch_asynch. Пожалуйста, дайте мне знать, как это исправить. Это. Будет здорово, если вы сможете предоставить различные способы его передачи, если это применимо.

main

    dispatch_block_t ^block1(int, int) = ^(int x1, int delay) {
        [NSThread sleepForTimeInterval: delay];
    };
    dispatch_queue_t defaultPriority = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_queue_t backgroundPriority = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

    dispatch_async(defaultPriority, block1(2, 3000));
 synchName andId: (NSString *) synchId;

@end

1 Ответ

0 голосов
/ 03 ноября 2019

dispatch_block_t определяется как замыкание, которое не принимает параметров:

typedef void (^dispatch_block_t)(void);

Поэтому нет смысла говорить «Я хочу определить замыкание с двумя параметрами и определить его какa dispatch_block_t ”, потому что dispatch_block_t не принимает параметров.

Итак, давайте предположим, что вы хотите определить метод, который принимает блок с двумя параметрами. Вы бы сделали это так:

- (void)foo:(void (^)(int, int))block {
    dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);

    dispatch_async(queue, ^{
        block(42, 3);
    });
}

Обратите внимание, я не просто передаю свой block в качестве второго параметра напрямую dispatch_async, потому что dispatch_block_t не принимает параметров, тогда как мой блокпринимает два параметра. Итак, я использую синтаксис ^{...} для второго параметра в dispatch_async, и внутри этого блока я вызываю мой block с двумя предоставленными параметрами.

В любом случае, вы бы назвали его так:

void (^block1)(int, int) = ^(int value, int delay) {
    [NSThread sleepForTimeInterval:(NSTimeInterval)delay];
    NSLog(@"value = %d", value);
};
[self foo:block1];

или

[self foo:^(int value, int delay) {
    [NSThread sleepForTimeInterval:(NSTimeInterval)delay];
    NSLog(@"value = %d", value);
}];

Если вы также хотите передать два параметра для блока в foo, затем добавьте эти два параметра:

- (void)fooWithValue:(int)value delay:(int)delay block:(void (^)(int, int))block {
    dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);

    dispatch_async(queue, ^{
        block(value, delay);
    });
}

И вы бы назвали это так:

void (^block1)(int, int) = ^(int value, int delay) {
    [NSThread sleepForTimeInterval:(NSTimeInterval)delay];
    NSLog(@"value = %d", value);
};

[self fooWithValue:2 delay:3 block:block1];

Кстати, если вы хотите упростить этот синтаксис, вы можете определить свой собственный псевдоним типа блока:

typedef void (^CustomBlockType)(int, int);

(Обратите внимание, это похоже на определение dispatch_block_t, за исключением того, что оно принимает два целых числа.)

Тогда вы можете делать такие вещи, как:

- (void)fooWithValue:(int)value delay:(int)delay block:(CustomBlockType)block {
    dispatch_queue_t queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0);

    dispatch_async(queue, ^{
        block(value, delay);
    });
}

И

CustomBlockType block1 = ^(int value, int delay) {
    [NSThread sleepForTimeInterval:(NSTimeInterval)delay];
    NSLog(@"value = %d", value);
};

[self fooWithValue:2 delay:3 block:block1];

Этот синтаксис для блоков довольно запутанный для запоминания, поэтому http://goshdarnblocksyntax.com может быть хорошей чит-таблицей, если вы забудете синтаксис.


Кстати, ваш кодссылается на «задержку» в сочетании с sleepForTimeInterval. Как правило, вы не хотите использовать sleepForTimeInterval. Обычно вы используете dispatch_after, например, чтобы сделать что-то за 3 секунды, вы должны сделать:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self doSomething];
});
...