};
Блоковые объекты инициируются точно так же, как и функции на языке C. Если у них есть какие-либо параметры, то вы передаете их так, как и в функции C. Любое возвращаемое значение можно получить точно так же, как и возвращаемое значение функции на языке C. Вот пример:
NSString* (^intToString)(NSUInteger) = ^(NSUInteger paramInteger){
NSString *result = [NSString stringWithFormat:@"%lu",
(unsigned long)paramInteger];
return result;
};
— (void) callIntToString{
NSString *string = intToString(10);
NSLog(@"string = %@", string);
}
Метод callIntToString языка Objective-C вызывает блоковый объект intToString, передавая этому блоковому объекту в качестве единственного параметра значение 10 и помещая возвращаемое значение данного блокового объекта в локальную переменную string.
Теперь, когда мы знаем, как писать блоковые объекты в виде независимых блоков кода, рассмотрим передачу блоковых объектов как передачу параметров методам языка Objective-C. Чтобы понять смысл следующего примера, нужно прибегнуть к определенным абстракциям.
Предположим, у нас есть метод Objective-C, принимающий целое число и выполняющий над ним какое-либо преобразование. Такое преобразование может меняться в зависимости от того, что еще происходит в программе. Мы уже знаем, что у нас будет целое число в качестве ввода и строка в качестве вывода, но сам процесс преобразования поручим блоковому объекту — а этот объект может быть иным при каждом вызове метода. Следовательно, в качестве параметров данный метод будет принимать и целое число, которое необходимо преобразовать, и тот блок, который будет выполнять преобразование.
Для блокового объекта воспользуемся тем же блоковым объектом intToString, который мы реализовали в примере 7.1. Теперь нам нужен метод на языке Objective-C, который будет принимать в качестве параметра беззнаковое целое число, а в качестве еще одного параметра — блоковый объект. С беззнаковым целым в качестве параметра все просто, но как сообщить методу, что он должен принимать блоковый объект того же типа , к которому относится блоковый объект intToString? Сначала определяем псевдоним сигнатуры блокового объекта intToString (с помощью ключевого слова typedef) и таким образом сообщаем компилятору, какие параметры должен принимать блоковый объект:
typedef NSString* (^IntToStringConverter)(NSUInteger paramInteger);
Объявление typedef просто сообщает компилятору, что блоковые объекты, принимающие в качестве параметра целое число и возвращающие строку, можно представлять с помощью обычного идентификатора, называемого IntToStringConverter. Итак, пойдем дальше и напишем метод на Objective-C, который будет принимать в качестве параметров и целое число, и блоковый объект типа IntToStringConverter:
— (NSString *) convertIntToString-NSUInteger)paramInteger
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. Теперь я могу воспользоваться типом данных, чтобы стимулировать правильную работу методов, а при самой операции передачи блокового объекта использовать его имя.
Читать дальше
Конец ознакомительного отрывка
Купить книгу