Сохранить цикл с очередью операций

Читая блог о параллелизме в iOS, я наткнулся на следующий код:

__weak id weakSelf = self;
[self.operationQueue addOperationWithBlock:^{
    NSNumber* result = findLargestMersennePrime();
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        MyClass* strongSelf = weakSelf;
        strongSelf.textLabel.text = [result stringValue];
    }];
}];

Автор объясняет, что использование weakref необходимо, поскольку:

нам нужно сделать слабую ссылку на себя, в противном случае мы создаем цикл сохранения (блок сохраняет себя, очередь частных операций сохраняет блок, а сама сохраняет очередь операций). Внутри блока мы конвертируем его обратно в сильную ссылку, чтобы убедиться, что он не освобождается при выполнении блока.

Я могу понять, почему блок сохранил себя, но я не понимаю, почему (и где именно) личная очередь операций сохраняет блок и когда / где само повторяет очередь операций. Любое объяснение будет высоко ценится.

1 ответ

Решение

Попробуйте написать этот код без слабой ссылки:

[self.operationQueue addOperationWithBlock:^{
    NSNumber* result = findLargestMersennePrime();
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        self.textLabel.text = [result stringValue];
    }];
}];

чтобы этот код работал - компилятор сохраняет ссылку на self в operationQueue чтобы избежать ситуации, когда self удаляется из памяти и self.textLabel.text = .. выполняется, поэтому он пытается гарантировать, что объект будет жив.

Вот где фактически создается цикл:

  1. self сохраняет operationQueue (это означает, что operationQueue не может быть удалена, пока self жива)
  2. OperationQueue сохраняет себя (это означает, что self не может быть удалено, пока OperationQueue жива)

чтобы избежать этого - вы создаете недельную ссылку, поэтому вы исключаете 2-й срок хранения

PS. "Блок" является частью операции Queue, поэтому в этой схеме мы можем использовать только 2 элемента.

Другие вопросы по тегам