Главная » iPhone, Objective-C, Программирование для iOS и MacOS » Передача блока Objective-C

0

Поскольку devowelizer является переменной, ее можно передать в аргументе. Класс NSArray содержит метод с именем enumerateObjectsUsingBloсk:. Единственным аргументом этого метода является блок, который выполняется один раз для каждого объекта в массиве.

Включите     в     файл     main.m     следующий     код,     который     вызывает

enumerateObjectsUsingBlock: с блоком devowelizer, а затем выводит строки с удаленными гласными.

int main (int argc, const char * argv[])

{

@autoreleasepool {

// создание массива строк, из которых удаляются гласные,

// и контейнера для новых строк

NSArray *oldStrings = [NSArray arrayWithObjects:

@"Sauerkraut", @"Raygun", @"Big Nerd Ranch",

@"Mississippi", nil]; NSLog(@"old strings: %@", oldStrings);

NSMutableArray *newStrings = [NSMutableArray array];

// создание списка символов, удаляемых из строки NSArray *vowels = [NSArray arrayWithObjects:

@"a", @"e", @"i", @"o", @"u", nil];

// объявление блочной перменной

void (^devowelizer)(id, NSUInteger, BOOL *);

// присваивание блока переменной

devowelizer = ^(id string, NSUInteger i, BOOL *stop) {   NSMutableString *newString = [NSMutableString stringWithString:string];

// перебор массива гласных и замена всех вхождений

// элементов пустой строки

for (NSString *s in vowels) {

NSRange fullRange = NSMakeRange(0, [newString length]); [newString replaceOccurrencesOfString:s

withString:@"" options:NSCaseInsensitiveSearch range:fullRange];

}

[newStrings addObject:newString];

}; // конец присваивания блока

// перебор элементов массива с блоком

[oldStrings enumerateObjectsUsingBlock:devowelizer]; NSLog(@"new strings: %@", newStrings);

}

return 0;

}

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

2011-­‐09-­‐03 10:27:02.617 VowelMovement[787:707] old strings: ( Sauerkraut,

Raygun,

"Big Nerd Ranch", Mississippi

)

2011-­‐09-­‐03 10:27:02.618 VowelMovement[787:707] new strings: ( Srkrt,

Rygn,

"Bg Nrd Rnch", Msssspp

)

Важно помнить, что в аргументе enumerateObjeсtsUsingBlock: может передаваться не любой блок. Метод требует, чтобы ему передавался «блок, который получает объект, целое число и указатель на BOOL, и не возвращает ничего». Вот почему блок; присвоенный devowelizer, был построен именно так. Три его аргумента предназначены специально для перебора содержимого массива.

Первый аргумент содержит указатель на текущий объект. Обратите внимание:

указатель имеет тип id, поэтому он будет работать независимо от того, какие объекты хранятся в массива. Во втором аргументе передается значение NSUInteger – индекс текущего объекта. Третий объект содержит указатель на значение BOOL, по умолчанию равное NO. Если вы хотите, чтобы перебор элементов массива завершился после текущей итерации, измените его на YES .

Включите дополнительную проверку в начало присваивания блока:

devowelizer = ^(id string, NSUInteger i, BOOL *stop){

NSRange yRange = [string rangeOfString:@"y"

options:NSCaseInsensitiveSearch];

// нашли «y»?

if (yRange.location != NSNotFound) {

*stop = YES; // отмена дальнейшей итерации return;     // прерывание текущей итерации

}

NSMutableString *newString = [NSMutableString stringWithString:string];

// перебор массива гласных и замена всех вхождений

// элементов пустой строкой for (NSString *s in vowels) {

NSRange fullRange = NSMakeRange(0, [newString length]); [newString replaceOccurrencesOfString:s

}

[newStrings addObject:newString];

}; // конец присваивания блока

Новый фрагмент проверяет, содержит ли строка текущей итерации букву «y» в верхнем или нижнем регистре. Если вхождение найдено, то указателю задается значение YES (отменяющее последующие итерации), после чего текущий перебор прерывается.

Постройте и запустите программу. И снова на консоль выводятся два массива,

но на этот раз перебор отменяется на второй итерации, когда блок обнаруживает слово с буквой «y». от всего массива остается только Srkrt.

Итак, мы немного потренировались в использовании блоков. Давайте вернемся и посмотрим, как блоки помогают в решении проблемы логической удаленности фрагментов кода в программах. При использовании обратного вызова – как в главе 24, где использовалась следующая строка кода:

[[NSNotificationCenter defaultCenter]

addObserver:logger selector:@selector(zoneChange:)

name:NSSystemTimeZoneDidChangeNotification object:nil];

вы задаете метод (обычно с использованием @selector( )), после чего реализуете этот метод где-то в другом месте файла:

-­‐    (void)zoneChange:(NSNotification   *)note

{

NSLog(@"The system time zone has changed!");

}

Также возможно использование метода NSNotificationCenter addObserverForName:object:queue:usingBlock: и передачей блока. При использовании этого метода NSNotificationCenter происходит непосредственная передача инструкций, так что вам не придется размещать код обратного вызова где-то в  другом  месте.  Любой  читатель  вашего  кода  увидит  инструкции  и  сообщение,

отправляемое NSNotificationCenter, в одном фрагменте кода. (Именно такое изменение в программе Callbacks вам будет предложено реализовать в упражнении в конце этой главы.)

Источник: Аарон Хилегас, «Objective-C. Программирование для iOS и MacOS», 2012 г.

По теме:

  • Комментарии