Перед прочтением рекомендую прочитать первую часть. В первой части мы узнали как создавать блоки и хранить их в переменных, передавать в методы и вызывать их. В этой части поговорим об особенностях использования блоков.

Взаимодействие с внешними переменными

Рассмотрим пример:

BOOL flag = YES;
void(^block)(NSString *) = ^(NSString* s)
{
    if ( flag )
        NSLog(@"String: %@", s);
};
block(@"Hello, World");

Тут все просто — блок выводит в консоль входящую строку, если флаг установлен в YES. Если мы сделаем вот так:

BOOL flag = YES;
void(^block)(NSString *) = ^(NSString* s)
{
    if ( flag )
        NSLog(@"String: %@", s);
};
flag = NO;
block(@"Hello, World");

Строка всеравно появиться в консоли, хотя флаг выставлен в NO. В чем же дело? Все дело в том, что блок копирует значение всех переменных и далее использует скопированное значение. Это относится к простейшим типам и структурам (не к указателям на объекты). Если мы хотим, чтобы блок не копировал значение переменной, а использовал ее истинное значение, необходимо пользоваться модификатором __block.

__block BOOL flag = YES;
void(^block)(NSString *) = ^(NSString* s)
{
    if ( flag )
        NSLog(@"String: %@", s);
};
flag = NO;
block(@"Hello, World");

Теперь, благодаря __block, блок будет использовать истинное значение переменной flag и не выведет строку.

А как же обстоят дела с указателями на объекты? По-умолчанию блок вызывает retain для всех указателей на объекты, которые в нем используются. Если использовать модификатор __block то retain для них не вызывается.

На этом все. В следующей части мы рассмотрим типы блоков и экземплярами каких классов они являются.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *