Как использовать переменные по ссылке в блоке кода? - PullRequest
0 голосов
/ 02 августа 2011

У меня есть блок, который я отправляю в очередь, и я хочу, чтобы блок выполнялся только при выполнении определенного условия. Это выглядит примерно так:

bool hi = YES;
dispatch_async(queue, ^{
    if (hi == YES)
        do stuff;
});

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

Я просмотрел документацию и нашел директиву __block, которая, похоже, может мне помочь, но не сработала. Я пробовал:

__block bool hi = YES;
dispatch_async(queue, ^{
    if (hi == YES)
        do stuff;
});

и

bool hi = YES;
dispatch_async(queue, ^{
    __block boolean hi2 = hi;
    if (hi2 == YES)
        do stuff;
});

И ни один из них, похоже, не работает.

Ответы [ 2 ]

2 голосов
/ 02 августа 2011

__block BOOL hi должен делать то, что вы хотите. Обратите внимание, что если вы отправляете асинхронно, тогда есть вероятность, что if (hi == YES) будет запущен, прежде чем вы измените hi на NO, даже если остальная часть блока - нет. Что вам действительно нужно делать, так это периодически проверять привет, чтобы увидеть, стоит ли продолжать работать, вместо того, чтобы проверять один раз, стоит ли начинать.

1 голос
/ 02 августа 2011

Я не эксперт по блокам, поэтому я не знаю, есть ли способ не фиксировать значение примитивной переменной внутри нее (но я думаю, что нет). Решения, которые могут прийти в голову, - это использование указателя или номера NSNumber для решения проблемы.

Указатель

/* this obviously needs to still be around to be dereferenced when the block executes */
BOOL hi = YES; 
BOOL* hiPtr = &hi;

dispatch_async(queue, ^{
    if (*hiPtr == YES)
        do stuff;
});

NSNumber

/ * это, очевидно, должно быть вокруг, чтобы разыменовываться, когда блок выполняется * /

__block NSNumber* hi = [NSNumber numberWithBool: YES]; 

dispatch_async(queue, ^{
    if ([hi boolValue] == YES)
        do stuff;
});
...