Чтение онлайн

ЖАНРЫ

iOS. Приемы программирования

Нахавандипур Вандад

Шрифт:

usingBlockObject-IntToStringConverter)paramBlockObject{

return paramBlockObject(paramInteger);

}

Теперь требуется просто вызвать метод convertIntToString:, сопровождаемый объектом на наш выбор (пример 7.2).

Пример 7.2. Вызов блокового объекта в другом методе

— (void) doTheConversion{

NSString *result = [self convertIntToString:123

usingBlockObject: intToString];

NSLog(@"result = %@", result);

}

Теперь,

когда мы немного разбираемся в независимых блоковых объектах, поговорим о встраиваемых блоковых объектах. В только что рассмотренном методе doTheConversion мы передавали методу convertIntToString: usingBlockObject: в качестве параметра блоковый объект intToString. Что если бы у нас не было в распоряжении готового блокового объекта, который можно было бы передать этому методу? На самом деле это не доставило бы нам никаких проблем. Как уже упоминалось, блоковые объекты — это функции первого класса и их можно создавать во время исполнения. Рассмотрим альтернативную реализацию метода doTheConversion (пример 7.3).

Пример 7.3. Блоковый объект, определенный в виде функции

— (void) doTheConversion{

IntToStringConverter inlineConverter = ^(NSUInteger paramInteger){

NSString *result = [NSString stringWithFormat:@"%lu",

(unsigned long)paramInteger];

return result;

};

NSString *result = [self convertIntToString:123

usingBlockObject: inlineConverter];

NSLog(@"result = %@", result);

}

Сравните примеры 7.1 и 7.3. Я удалил имевшийся в первом варианте код, в котором мы формировали сигнатуру блокового объекта. Данная сигнатура состояла из имени и аргумента — (^intToString) (NSUInteger). Остальную часть блокового объекта я не трогаю, и теперь он становится анонимным объектом. Но это не означает, что я никак не могу сослаться на блоковый объект. С помощью знака равенства (=) я присваиваю блоковый объект типу и имени: IntToStringConverter inlineConverter. Теперь я могу воспользоваться типом данных, чтобы стимулировать правильную работу методов, а при самой операции передачи блокового объекта использовать его имя.

Кроме того способа создания встраиваемых блоковых объектов, который только что был продемонстрирован, существует способ создания блокового объекта на этапе передачи его как параметра:

— (void) doTheConversion{

NSString *result =

[self convertIntToString:123

usingBlockObject: ^NSString *(NSUInteger paramInteger) {

NSString *result = [NSString stringWithFormat:@"%lu",

(unsigned long)paramInteger];

return result;

}];

NSLog(@"result = %@", result);

}

Сравните

этот пример с примером 7.2. Оба метода используют блоковый объект с применением синтаксиса usingBlockObject. Но, в то время как при применении первого варианта мы ссылались по имени на предварительно определенный блоковый объект (intToString), во втором варианте блоковый объект создается на лету. В этом коде мы создали встраиваемый блоковый объект, который передается методу convertIntToString: usingBlockObject: как второй параметр.

7.2. Доступ к переменным в блоковых объектах

Постановка задачи

Необходимо понять разницу между доступом к переменным в методах Objective-C и доступом к этим переменным в блоковых объектах.

Решение

Вот краткое обобщение того, что необходимо знать о переменных в блоковых объектах.

Локальные переменные в блоковых объектах работают точно так же, как и в методах Objective-C.

• При работе со встраиваемыми блоковыми объектами к локальным относятся не только те переменные, которые определены внутри блока, но и те, что определены в методе, реализующем данный блоковый объект (чуть позже рассмотрим примеры).

• Нельзя ссылаться на self в независимых блоковых объектах, реализованных в классе Objective-C. Если необходим доступ к self, то вам нужно передать его объект блоковому объекту в качестве параметра. Чуть позже рассмотрим на примере и такую ситуацию.

• Во встраиваемом блоковом объекте на self можно ссылаться лишь в тех случаях, когда self присутствует в лексической области видимости, в рамках которой и создается блоковый объект.

• При работе со встраиваемыми блоковыми объектами локальные переменные, определяемые внутри реализации блокового объекта, доступны для считывания, но не для записи. Однако есть и исключение. Блоковый объект может записывать информацию в такие переменные, если они определены с типом хранения __block. Пример мы также рассмотрим.

• Предположим, у вас есть блоковый объект типа NSObject, а внутри реализации этого объекта вы используете блоковый объект с GCD. Внутри данного блокового объекта у вас будет доступ для чтения и записи к объявленным свойствам того NSObject, внутри которого реализован блок.

• Вы можете получать доступ к объявленным свойствам NSObject внутри независимых блоковых объектов, только если вы работаете с методами-установщиками и методами-получателями этих свойств. Вы не сможете получить доступ к объявленным свойствам объекта внутри независимого блокового объекта с помощью точечной нотации.

Обсуждение

Сначала научимся работать с переменными, которые являются локальными для реализаций двух блоковых объектов. Один из этих блоковых объектов будет встраиваемым, а другой — независимым:

void (^independentBlockObject)(void) = ^(void){

NSInteger localInteger = 10;

NSLog(@"local integer = %ld", (long)localInteger);

localInteger = 20;

NSLog(@"local integer = %ld", (long)localInteger);

};

При активизации этого блокового объекта те значения, которые мы присваиваем, выводятся в окне консоли:

Поделиться с друзьями: