Нужно ли ключевое слово __block для записи в l oop в объективе C при изменении массива или словаря? - PullRequest
0 голосов
/ 29 апреля 2020

Требуется ли ключевое слово __block для записи в l oop в цели C при переходе в массив или словарь?

__block NSMutableArray *xxxx = [NSMutableArray new]; // is __block needed?
for (obj in objs) {
    [xxx addObject];
}

Ответы [ 3 ]

2 голосов
/ 30 апреля 2020

Нет, это не так. Ключевое слово __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;
    }
}];
0 голосов
/ 30 апреля 2020

Нет, в размещенном вами фрагменте кода модификатор __block не требуется.

0 голосов
/ 30 апреля 2020

Нет. __block необходимо, если значение переменной изменяется внутри блока, например.

__block NSUInteger sum = 0;
[objs enumerateObjectsUsingBlock:
^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    sum += obj.number; // just imaginary
}];

, в вашем случае значение переменной является указателем, и оно не изменяется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...