блоки и ARC - копирование или сбой при сборке релиза (вызвано уровнем оптимизации)
Я использую Xcode 4.3.3 и разрабатываю для iOS 5.0+. При разработке приложения ARC для iOS я начал использовать блоки в качестве механизма обратного вызова для асинхронных операций. Приложение отлично работает в симуляторе и на устройстве.
Затем я запустил его в качестве профилировщика в первый раз, и он сразу же начал падать на меня - в частности, EXC_BAD_ACCESS при попытке вызвать первый блок обратного вызова.
После небольшого исследования стало ясно, что различие в поведении объясняется тем, что профилировщик работает в «режиме выпуска». по умолчанию - в частности, с уровнем оптимизации, установленным на «Fastest, Smallest [-Os]» & quot; вместо "Нет [-O0]".
Например, следующий код (упрощенный для этого вопроса) вылетает при попытке выполнить callbackBlock:
- (void) setCallbackBlock:(void (^)(NSString *input))block
{
callbackBlock = block;
}
- (void) invokeCallbackWithInput:(NSString *)input
{
if (callbackBlock) {
callbackBlock(input);
}
}
Отладка в нем, вызов setCallbackBlock с уровнем оптимизации, установленным на «None», входящий блок будетNSStackBlock
и callbackBlock станетNSMallocBlock
.
Однако с уровнем оптимизации «Самый быстрый, самый маленький» он оставалсяNSStackBlock
.
Изменение установочного кода для использования[block copy]
решает проблему сбоя (на основеiOS 5 блокирует сбой только с Release Build).
Однако другой связанный с этим вопрос указывает на то, что это не должно быть необходимо с ARC - переменные блока копируются в кучу в ARC -Почему блок Objective-C все еще работает, не копируя его в кучу?
Итак, мой вопрос: что здесь происходит и почему? (Кроме того, как оба эти ответа могут быть правильными ...?)
Edit: To clarify how callbackBlock is being declared - just above my @implementation where those methods are is this:
@interface MyClass ()
{
void (^callbackBlock)(NSString *input);
}
@end