Вопреки распространенному заблуждению, ARC не снимает автоматически блокировку блоков, передаваемых в качестве аргументов методам .Снятие стека происходит автоматически только при возврате блока из метода / функции.
Т.е. this ....
[dict setObject: ^{;} forKey: @"boom"];
... потерпит крах, если dict
выживет послеобласть действия, и вы пытаетесь использовать блок (на самом деле, в данном случае это не так, потому что это статический блок, но это деталь компилятора, на которую нельзя полагаться).
Это задокументировано здесь :
Как блоки работают в 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];
Это не только решит проблему блока-как-параметра, но также создаст только одну копию блока для всех потенциальных применений.
Однако вопрос все еще стоит: почему это происходит?Почему NSDictionary не хранит блок?Имеет ли это какое-то отношение к тому факту, что я нацеливаюсь на iOS 4.3, и поэтому ARC должен быть встроен как статическая библиотека?
Тогда происходит нечто странное.По совпадению, я использовал блоки как значения в приложении на основе ARC на прошлой неделе, и он работает нормально.
У вас есть минимальный удобный пример?