ПРОГРАММИРОВАНИЕ ПОД IPHONE, IPAD OBJECTIVE-C Часть 1

Блоки

Совсем недавно Apple анонсировала приятное дополнение к языку Objective-C — блоки. Это неоднозначное слово и первое, что приходит на ум — это блок-схема программы или составная структура операторов, которая существует в С. Но Apple придает новое значение слову «блок» — это вложенная функция. То есть, функция, реализация которой описана внутри другой функции называется блоком. Слово «недавно» в начале урока я употребил не зря. Дело в том, что эта фишка была добавлена в iOS 4.0, то есть, на версии прошивки ниже четвертой блоки работать не будут. Блок часто еще называют замыканием (наверное потому, что эта функция замкнута внутри другой функции). Блок имеет доступ к переменным функции внешней. Вложенная функция может продолжать работать даже после того как внешняя — закончила работу. При этом, ссылки на переменные внешней функции, которые использует внутренняя будут действительны до завершения работы вложенной функции. Но не будем углубляться в подробности, а посмотрим как выглядит самый простой блок:

<code data-result="[object Object]">int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    return num * multiplier;
};</code>

Этот пример я попытался объяснить на следующем рисунке:

Если вы объявляете блок как переменную — вы можете использовать дальше ее внутри функции:

<code data-result="[object Object]">int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    return num * multiplier;
};

NSLog(@"%i", myBlock(3));</code>
Существует несколько методов использования блока в качестве аргумента, для выполнения операцию над массивом, или использовать в качестве обратного вызова после завершения операции. Следующий пример показывает, как использовать блок с NSArraysortedArrayUsingComparator методом. Этот метод принимает один аргумент — блок. Для примера, в этом случае блок определяется какNSComparator локальной переменной:
<code data-result="[object Object]">NSArray *stringsArray = [NSArray arrayWithObjects:
                         @"1",
                         @"3",
                         @"7",
                         @"0",
                         @"9", nil];

NSComparator finderSortBlock = ^(id string1, id string2) {
    return [string1 compare:string2];
};

NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
NSLog(@"finderSortArray: %@", finderSortArray);</code>

Как я уже говорил, блок имеет доступ к переменным внешней функции, но изменять эти переменные он не может. К примеру, следующий код не будет скомпилирован:

<code data-result="[object Object]">int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    multiplier = 10;
    return num * multiplier;
};

NSLog(@"%i", myBlock(3));</code>

Компилятор выдаст ошибку «Variable is not assignable (missing __block type specifier)». Более того, он нам подсказывает, что нужно добавить спецификатор __block.

<code data-result="[object Object]">__block int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    multiplier = 10;
    return num * multiplier;
};

NSLog(@"%i", myBlock(3));</code>

Такая конструкция сработает без ошибки и выведет в консоль число 30.

Блоки значительно облегчают процесс программирования и уменьшают объем кода, если использовать их функции обратного вызова (callbacks). Давайте посмотрим, как это выглядит в случае с анимацией:

<code data-result="[object Object]">[UIView animateWithDuration:0.5f 
                      delay:0.0f 
                    options:UIViewAnimationOptionBeginFromCurrentState 
                 animations:^{
                     self.view.alpha = 0.5f;
                 }
                 completion:^(BOOL finished){self.view.alpha = 1.0f;}];</code>

Этот код делает полупрозрачный основной UIView (за пол секунды), а по окончанию анимации восстанавливает его прозрачность. Для сравнения, вы можете посмотреть как сделать такой же эффект без блоков в уроке Промежуточная анимация в iOS (там вам понадобится как минимум два метода).

Comments are closed.