Objective-C Language
Блоки
Поиск…
Синтаксис
// Объявляем локальную переменную:
returnType (^ blockName) (parameterType1, parameterType2, ...) = ^ returnType (аргумент1, аргумент2, ...) {...};
// Объявляем как свойство:
@property (nonatomic, copy, nullability) returnType (^ blockName) (parameterTypes);
// Объявляем как параметр метода:
- (void) someMethodThatTakesABlock: (returnType (^ nullability) (parameterTypes)) blockName;
// Объявляем в качестве аргумента вызов метода:
[someObject someMethodThatTakesABlock: ^ returnType (параметры) {...}];
// Объявляем как typedef:
typedef returnType (^ TypeName) (parameterTypes);
TypeName blockName = ^ returnType (parameters) {...};
// Объявляем функцию C возвращать объект блока:
BLOCK_RETURN_TYPE (^ имя_функции (функциональные параметры)) (BLOCK_PARAMETER_TYPE);
замечания
Блоки определяются спецификацией языка для блоков для C, Objective-C, C ++ и Objective-C ++.
Кроме того, блоки ABI определяются спецификацией реализации блоков .
Блоки как параметры метода
- (void)methodWithBlock:(returnType (^)(paramType1, paramType2, ...))name;
Определение и присвоение
Блок, который выполняет добавление двух чисел двойной точности, назначенных для addition
переменной:
double (^addition)(double, double) = ^double(double first, double second){
return first + second;
};
Затем блок можно вызвать так:
double result = addition(1.0, 2.0); // result == 3.0
Блокирует как свойства
@interface MyObject : MySuperclass
@property (copy) void (^blockProperty)(NSString *string);
@end
При назначении, поскольку self
сохраняет blockProperty
, блок не должен содержать сильную ссылку на self. Эти взаимные сильные ссылки называются «циклом сохранения» и будут препятствовать выпуску любого объекта.
__weak __typeof(self) weakSelf = self;
self.blockProperty = ^(NSString *string) {
// refer only to weakSelf here. self will cause a retain cycle
};
Это маловероятно, но self
может быть освобожден внутри блока, где-то во время выполнения. В этом случае weakSelf
становится nil
и все сообщения к нему не имеют желаемого эффекта. Это может оставить приложение в неизвестном состоянии. Этого можно избежать, сохранив weakSelf
с __strong
ivar во время выполнения блока и очистив потом.
__weak __typeof(self) weakSelf = self;
self.blockProperty = ^(NSString *string) {
__strong __typeof(weakSelf) strongSelf = weakSelf;
// refer only to strongSelf here.
// ...
// At the end of execution, clean up the reference
strongSelf = nil;
};
Блокировка Typedefs
typedef double (^Operation)(double first, double second);
Если вы объявляете тип блока как typedef, вы можете использовать новое имя типа вместо полного описания аргументов и возвращаемых значений. Это определяет Operation
как блок, который принимает два удвоения и возвращает double.
Тип может использоваться для параметра метода:
- (double)doWithOperation:(Operation)operation
first:(double)first
second:(double)second;
или как переменный тип:
Operation addition = ^double(double first, double second){
return first + second;
};
// Returns 3.0
[self doWithOperation:addition
first:1.0
second:2.0];
Без typedef это намного грязнее:
- (double)doWithOperation:(double (^)(double, double))operation
first:(double)first
second:(double)second;
double (^addition)(double, double) = // ...
Блокирует как локальные переменные
returnType (^blockName)(parameterType1, parameterType2, ...) = ^returnType(argument1, argument2, ...) {...};
float (^square)(float) = ^(float x) {return x*x;};
square(5); // resolves to 25
square(-7); // resolves to 49
Вот пример без возврата и без параметров:
NSMutableDictionary *localStatus;
void (^logStatus)() = ^(void){ [MYUniversalLogger logCurrentStatus:localStatus]};
// Insert some code to add useful status information
// to localStatus dictionary
logStatus(); // this will call the block with the current localStatus