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

ЖАНРЫ

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

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

Шрифт:

7.1. Создание блоковых объектов

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

Необходимо иметь возможность писать собственные блоковые объекты либо использовать блоковые объекты с классами из iOS SDK.

Решение

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

Обсуждение

Блоковые объекты могут быть либо встраиваемыми, либо записываемыми как отдельные блоки кода. Начнем с объектов второго

типа. Предположим, у нас есть метод языка Objective-C, принимающий два целочисленных значения типа NSInteger и возвращающий разницу двух этих значений в форме NSInteger. Разница получается в результате вычитания одного значения из другого:

— (NSInteger) subtract:(NSInteger)paramValue

from:(NSInteger)paramFrom{

return paramFrom — paramValue;

}

Очень просто, правда? Теперь преобразуем этот код Objective-C в классическую функцию языка C, обеспечивающую такую же функциональность. Это еще на шаг приблизит нас к пониманию синтаксиса блоковых объектов:

NSInteger subtract(NSInteger paramValue, NSInteger paramFrom){

return paramFrom — paramValue;

}

Как видите, синтаксис функции на C значительно отличается от синтаксиса аналогичной функции на языке Objective-C. Теперь рассмотрим, как можно написать ту же функцию в виде блокового объекта:

NSInteger (^subtract)(NSInteger, NSInteger) =

^(NSInteger paramValue, NSInteger paramFrom){

return paramFrom — paramValue;

};

Прежде чем перейти к детальному описанию синтаксиса блоковых объектов, приведу еще несколько примеров. Предположим, что у нас есть функция на языке C, принимающая параметр типа NSUInteger (беззнаковое целое число) и возвращающая строку типа NSString. Вот как данная функция реализуется на C:

NSString* intToString (NSUInteger paramInteger){

return [NSString stringWithFormat:@"%lu",

(unsigned long)paramInteger];

}

Чтобы научиться форматировать строки с применением системонезависимых указателей формата на языке Objective-C, ознакомьтесь с String Programming Guide in the iOS Developer Library (Руководство по программированию строк в библиотеке разработчика iOS). Адрес документа на сайте Apple: https://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/Strings/Articles/formatSpecifiers.html.

Блоковый объект, эквивалентный данной функции языка C, показан в примере 7.1.

Пример 7.1. Образец блокового объекта, определенного в виде функции

NSString* (^intToString)(NSUInteger) = ^(NSUInteger paramInteger){

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

(unsigned long)paramInteger];

return result;

};

Простейший

независимый блоковый объект — это блоковый объект, возвращающий void и не принимающий никаких параметров:

void (^simpleBlock)(void) = ^{

/* Здесь реализуется блоковый объект. */

};

Блоковые объекты инициируются точно так же, как и функции на языке 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

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