Ответ 1
Вопреки популярной ошибочной концепции ARC автоматически не деблокирует блоки, переданные в качестве аргументов методам. Он только автоматически деактивируется, когда блок возвращается из метода/функции.
т.е. это....
[dict setObject: ^{;} forKey: @"boom"];
... произойдет сбой, если dict
выйдет за пределы области действия и вы попытаетесь использовать блок (на самом деле это не будет в этом случае, потому что это статический блок, но это подробная информация о компиляторе, t полагаться).
Это описанное здесь:
Как блоки работают в ARC?
Блоки "просто работают", когда вы передаете блоки вверх по стеку в режиме ARC, например как в возвращении. Вам больше не нужно вызывать Block Copy. Вы все равно необходимо использовать [^ {} copy] при передаче "вниз" стека в
arrayWithObjects:
и другие методы, которые сохраняют.
Поведение возвращаемого значения может быть автоматизировано, потому что всегда правильно возвращать блок на основе кучи (и всегда является ошибкой для возврата блока на основе стека). В случае блока-аргумента невозможно автоматизировать поведение таким образом, чтобы это было очень эффективным и всегда правильным.
Вероятно, анализатор должен был предупредить об этом использовании. Если это не так, укажите ошибку.
(Я взял стек, когда имел в виду кучу. Извините.)
Компилятор не автоматизирует блоки как параметры по нескольким причинам:
- ненужное копирование блока в кучу может быть значительным снижением производительности
- несколько копий блока могут значительно увеличить это ограничение производительности.
то есть:.
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
Если бы это означало четыре операции Block_copy(), и aBlock содержал значительное количество захваченного состояния, это было бы огромным потенциальным ударом.
• Есть только так много часов в день, и автоматизация обработки параметров изобилует неочевидными краевыми случаями. Если бы это было автоматически обработано в будущем, это можно было бы сделать без нарушения существующего кода, и, возможно, это будет сделано в будущем.
т.е. компилятор может сгенерировать:
aBlock = [aBlock copy];
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
doSomethingSynchronous(aBlock);
[aBlock release];
Это не только устранит проблему с блоком-как-param, но также создаст только одну копию блока во всех потенциальных целях.
Вопрос все еще стоит: почему это происходит? Почему NSDictionary хранит блок? Имеет ли это какое-то отношение к факту что я настроен на iOS 4.3, и поэтому ARC должен быть встроен как статический библиотека?
Затем происходит что-то странное. Кстати, я использовал блоки как значения в приложении на основе ARC на прошлой неделе, и он работает нормально.
Есть ли у вас минимальный пример?