Сохранить цикл с очередью операций
Читая блог о параллелизме в 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 = ..
выполняется, поэтому он пытается гарантировать, что объект будет жив.
Вот где фактически создается цикл:
- self сохраняет operationQueue (это означает, что operationQueue не может быть удалена, пока self жива)
- OperationQueue сохраняет себя (это означает, что self не может быть удалено, пока OperationQueue жива)
чтобы избежать этого - вы создаете недельную ссылку, поэтому вы исключаете 2-й срок хранения
PS. "Блок" является частью операции Queue, поэтому в этой схеме мы можем использовать только 2 элемента.