Objective-C Language
Bloki
Szukaj…
Składnia
// Zadeklaruj jako zmienną lokalną:
returnType (^ nazwa_bloku) (parametrType1, parametrType2, ...) = ^ returnType (argument1, argument2, ...) {...};
// Zadeklaruj jako właściwość:
@property (nonatomic, copy, nullability) returnType (^ blockName) (parameterTypes);
// Deklaracja jako parametr metody:
- (void) someMethodThatTakesABlock: (returnType (^ nullability) (parameterTypes)) blockName;
// Zadeklaruj jako argument wywołania metody:
[someObject someMethodThatTakesABlock: ^ returnType (parametry) {...}];
// Zadeklaruj jako typedef:
typedef returnType (^ TypeName) (parameterTypes);
TypeName blockName = ^ returnType (parametry) {...};
// Deklaracja funkcji C zwraca obiekt bloku:
BLOCK_RETURN_TYPE (^ nazwa_funkcji (parametry funkcji)) (BLOCK_PARAMETER_TYPE);
Uwagi
Bloki są określone w specyfikacji języka dla bloków dla C, Objective-C, C ++ i Objective-C ++.
Dodatkowo Bloki ABI są zdefiniowane w specyfikacji implementacji bloku .
Bloki jako parametry metody
- (void)methodWithBlock:(returnType (^)(paramType1, paramType2, ...))name;
Definiowanie i przypisywanie
Blok, który wykonuje dodawanie dwóch liczb podwójnej precyzji, przypisanych do addition
zmiennych:
double (^addition)(double, double) = ^double(double first, double second){
return first + second;
};
Blok można następnie wywołać w następujący sposób:
double result = addition(1.0, 2.0); // result == 3.0
Bloki jako właściwości
@interface MyObject : MySuperclass
@property (copy) void (^blockProperty)(NSString *string);
@end
Podczas przypisywania, ponieważ self
zachowuje blockProperty
, blok nie powinien zawierać silnego odwołania do self. Te wzajemnie silne odniesienia nazywane są „cyklem przechowywania” i zapobiegną uwolnieniu któregokolwiek z obiektów.
__weak __typeof(self) weakSelf = self;
self.blockProperty = ^(NSString *string) {
// refer only to weakSelf here. self will cause a retain cycle
};
Jest to bardzo mało prawdopodobne, ale self
może zostać zwolniona w bloku, gdzieś podczas wykonywania. W tym przypadku weakSelf
staje się nil
i wszystkie wiadomości do niego nie mają pożądanego efektu. Może to pozostawić aplikację w nieznanym stanie. Można tego uniknąć poprzez zachowanie weakSelf
z __strong
podczas wykonywania bloku, a następnie wyczyścić.
__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;
};
Block Typedefs
typedef double (^Operation)(double first, double second);
Jeśli zadeklarujesz typ bloku jako typedef, możesz użyć nazwy nowego typu zamiast pełnego opisu argumentów i zwracanych wartości. To definiuje Operation
jako blok, który przyjmuje dwa podwójne i zwraca podwójne.
Typ może być użyty jako parametr metody:
- (double)doWithOperation:(Operation)operation
first:(double)first
second:(double)second;
lub jako typ zmiennej:
Operation addition = ^double(double first, double second){
return first + second;
};
// Returns 3.0
[self doWithOperation:addition
first:1.0
second:2.0];
Bez typedef jest to znacznie bardziej bałagan:
- (double)doWithOperation:(double (^)(double, double))operation
first:(double)first
second:(double)second;
double (^addition)(double, double) = // ...
Bloki jako zmienne lokalne
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
Oto przykład bez zwrotu i bez parametrów:
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