— (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]
initWithObjects:@"obj1",
@"obj2", nil];
[array sortUsingComparator: ^NSComparisonResult(id obj1, id obj2) {
NSLog(@"self = %@", self);
/* Возвращаем значение для блокового объекта. */
return NSOrderedSame;
}];
}
Не внеся изменений в реализацию вашего блокового объекта, вы не сможете получить доступ к self в независимом блоковом объекте. При попытке скомпилировать данный код мы получим ошибку времени компиляции:
void (^incorrectBlockObject)(void) = ^{
NSLog(@"self = %@", self); /* self здесь не определен. */
};
Если вы хотите получить доступ к self в независимом блоковом объекте, просто передайте объект, представляемый self, вашему блоковому объекту в качестве параметра:
void (^correctBlockObject)(id) = ^(id self){
NSLog(@"self = %@", self);
};
— (void) callCorrectBlockObject{
correctBlockObject(self);
}
Этому параметру не обязательно присваивать имя self. Ему можно дать любое имя. Тем не менее если назвать этот параметр self, то можно будет просто собрать код блокового объекта позже и поместить его в реализацию метода на языке Objective-C. Не придется менять имя каждого экземпляра переменной на self, чтобы код был воспринят компилятором.
Рассмотрим объявленные свойства и посмотрим, как блоковые объекты могут получать к ним доступ. При работе со встраиваемыми блоковыми объектами можно применять точечную нотацию — она позволяет считывать информацию из объявленных свойств self или записывать в них данные. Допустим, например, что у нас в классе есть объявленное свойство типа NSString, которое называется stringProperty:
#import «AppDelegate.h»
@interface AppDelegate()
@property (nonatomic, copy) NSString *stringProperty;
@end
@implementation AppDelegate
Теперь не составляет труда получить доступ к этому свойству во встраиваемом блоковом объекте:
— (void) simpleMethod{
NSMutableArray *array = [[NSMutableArray alloc]
initWithObjects:@"obj1",
@"obj2", nil];
[array sortUsingComparator: ^NSComparisonResult(id obj1, id obj2) {
NSLog(@"self = %@", self);
self.stringProperty = @"Block Objects";
NSLog(@"String property = %@", self.stringProperty);
/* Возвращаем значение для блокового объекта. */
return NSOrderedSame;
}];
}
Но в независимом блоковом объекте нельзя использовать точечную нотацию для считывания объявленного свойства или записи информации в это свойство:
void (^correctBlockObject)(id) = ^(id self){
NSLog(@"self = %@", self);
/* Вместо этого используем метод-установщик */
self.stringProperty = @"Block Objects"; /* Ошибка времени компиляции */
/* Вместо этого используем метод-получатель. */
NSLog(@"self.stringProperty = %@",
self.stringProperty); /* Ошибка времени компиляции */
};
В данном сценарии будем пользоваться методом-установщиком и методом-получателем синтезированного свойства:
void (^correctBlockObject)(id) = ^(id self){
NSLog(@"self = %@", self);
/* Это будет работать нормально. */
[self setStringProperty:@"Block Objects"];
/* Это также будет работать нормально. */
NSLog(@"self.stringProperty = %@",
[self stringProperty]);
};
Когда дело касается встраиваемых блоковых объектов, необходимо учитывать лишь одно очень важное правило: встраиваемые блоковые объекты копируют значения для переменных в своей лексической области видимости. Если вы не понимаете, что это значит, — не волнуйтесь. Рассмотрим пример:
typedef void (^BlockWithNoParams)(void);
— (void) scopeTest{
NSUInteger integerValue = 10;
BlockWithNoParams myBlock = ^{
NSLog(@"Integer value inside the block = %lu",
(unsigned long)integerValue);
};
integerValue = 20;
/* Вызываем блок здесь после изменения
значения переменной integerValue. */
myBlock();
Читать дальше
Конец ознакомительного отрывка
Купить книгу