Рейтинговые книги
Читем онлайн iOS. Приемы программирования - Вандад Нахавандипур

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 63 64 65 66 67 68 69 70 71 ... 165

Объявление 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. Теперь я могу воспользоваться типом данных, чтобы стимулировать правильную работу методов, а при самой операции передачи блокового объекта использовать его имя.

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

— (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);

};

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

local integer = 10

local integer = 20

Пока все несложно. Теперь рассмотрим встраиваемые блоковые объекты и переменные, которые являются для них локальными:

— (void) simpleMethod{

NSUInteger outsideVariable = 10;

NSMutableArray *array = [[NSMutableArray alloc]

initWithObjects:@"obj1",

@"obj2", nil];

[array sortUsingComparator: ^NSComparisonResult(id obj1, id obj2) {

NSUInteger insideVariable = 20;

NSLog(@"Outside variable = %lu", (unsigned long)outsideVariable);

NSLog(@"Inside variable = %lu", (unsigned long)insideVariable);

/* Возвращаем значение для блокового объекта. */

return NSOrderedSame;

}];

}

Метод экземпляра sortUsingComparator:, относящийся к классу NSMutableArray, пытается сортировать изменяемый массив. Цель кода, приведенного в данном примере, — просто продемонстрировать использование локальных переменных. Можно и не задаваться тем, что именно делает этот метод.

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

— (void) simpleMethod{

__block NSUInteger outsideVariable = 10;

NSMutableArray *array = [[NSMutableArray alloc]

initWithObjects:@"obj1",

@"obj2", nil];

[array sortUsingComparator: ^NSComparisonResult(id obj1, id obj2) {

NSUInteger insideVariable = 20;

outsideVariable = 30;

NSLog(@"Outside variable = %lu", (unsigned long)outsideVariable);

NSLog(@"Inside variable = %lu", (unsigned long)insideVariable);

/* Возвращаем значение для блокового объекта. */

return NSOrderedSame;

}];

}

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

— (void) simpleMethod{

NSMutableArray *array = [[NSMutableArray alloc]

1 ... 63 64 65 66 67 68 69 70 71 ... 165
На этой странице вы можете бесплатно читать книгу iOS. Приемы программирования - Вандад Нахавандипур бесплатно.
Похожие на iOS. Приемы программирования - Вандад Нахавандипур книги

Оставить комментарий