Нет, это не так. Ключевое слово __block
требуется только при соблюдении нескольких условий:
- Существует Objective- C "блок" - сегмент кода, захваченный как объект, и
- Существует переменная, объявленная вне блока, и
- Значение переменной изменяется внутри блока
Это может быть более ясным в контрпримере. Где не вам нужно ключевое слово __block
?
Вам не нужно, когда ваш l oop является простым C l oop, включая простой for
циклы и циклы, которые используют NSFastEnumeration:
NSInteger sum = 0;
for (NSInteger i = 0; i < 10; i++) {
sum += i; // okay! this is a plain C for loop
}
NSArray *numbers = @[@1, @2, @3];
for (NSNumber *i in numbers) {
sum += [i integerValue]; // okay! this is an NSFastEnumeration object loop
}
Если у вас есть фактический блок Objective- C, он вам не нужен, если тело блока действительно не изменяет значение переменная. Это часто имеет место, если ваш блок отправляет объекту только сообщения Objective- C:
NSMutableArray *evenNumbers = [NSMutableArray array];
NSArray *numbers = @[@1, @2, @3];
[numbers enumerateObjectsUsingBlock:^(NSNumber * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj integerValue] % 2 == 0) {
[evenNumbers addObject:obj]; // okay! this is an ObjC message send, which does not mutate the pointer value of `evenNumbers`
}
}];
Единственный случай, когда вам это нужно, это когда ваш блок намеревается изменить значение переменной напрямую.
__block NSString *match = nil;
__block NSUInteger matchIndex = NSNotFound;
NSArray *candidates = @[@"foo", @"bar"];
[candidates enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if ([obj isEqual:@"foo"]) {
// these must be __block, because we are mutating their values in this ObjC block
match = obj;
matchIndex = idx;
*stop = YES;
}
}];