Каково время жизни объекта, объявленного в блоке в ARC? - PullRequest
1 голос
/ 15 января 2012

В моем понимании блоков и ARC есть пробел, с которым мне нужна помощь. Я получил отчет о сбое от тестера, который происходит из блока завершения анимации. Авария выглядит следующим образом:

Тип исключения: EXC_BAD_ACCESS (SIGSEGV)

Коды исключений: KERN_INVALID_ADDRESS в 0xf0000010

Это происходит внутри следующего блока завершения анимации (используется animateWithDuration:animations:completion:). Я меняю два контроллера представления, используя временную переменную:

{
    [current wasMovedOffScreen];
    PlayerViewController *temp = current;
    current = next;
    next = temp;
}

next = temp; - линия, на которой происходит сбой. Продолжительность анимации составляет 0,3 секунды.

Этот код выполняется внутри контроллера представления, который действует как контейнер для двух других контроллеров представления, используется для имитации пользователя, проходящего через список объектов, таких как контроллер навигации, но с рядом настроек, которые означали контроллер навигации не подходит для меня.

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

Если я изменю блок так, чтобы в реализации было объявлено temp (вместе с current и next), сбой прекращается. Однако мне кажется ненужным иметь класс ivar для чего-то, что по определению является локальным и временным.

Итак,

  • Почему ARC явно высвобождает temp во время этого процесса?
  • Каков будет правильный способ реализации этого? Есть ли какой-то пожизненный квалификатор, который я должен добавить к реализации блока?
  • Почему я не мог воспроизвести сбой на моем собственном устройстве или в симуляторе? Оба устройства были iPhone 4 с одинаковой версией iOS (5.0.1).

Ответы [ 2 ]

1 голос
/ 15 января 2012

Я не думаю, что проблема на самом деле ARC в этом случае. Переменные (включая локальные переменные) по умолчанию __strong, поэтому current следует сохранить в первом присваивании.

http://developer.apple.com/library/mac/#releasenotes/ObjectiveC/RN-TransitioningToARC/_index.html - см. Раздел «Спецификаторы переменных»

Если у вас есть сбой, который вы не можете воспроизвести самостоятельно, это всегда будет трудно исправить. Вы пытались запустить приложение вне отладчика? Загрузка отладчика иногда может изменить поведение. Кроме того, попробуйте отладку с помощью NSZombieEnabled или инструмента Instruments.app's zombie.

0 голосов
/ 15 января 2012

И если это действительно поддерживает вас, так как вы чередуете только два просмотра, вам на самом деле не нужен весь этот текущий / следующий бизнес. Ну, вы можете отслеживать ток, если хотите ... но вот идея.

Если у вас есть свойства:

@property (nonatomic, strong) UIViewController *controller1;
@property (nonatomic, strong) UIViewController *controller2;
@property (nonatomic, weak) UIViewController *currentController;

Тогда вы можете иметь метод:

- (id)swapControllers {
    // use the current controller to figure out what the next controller is, so
    // you don't have to do the two way swap. do in the completion, if you like.    
    UIViewController *nextController = ([self.currentController isEqual:self.controller1]) ? self.controller1 : self.controller2;
    [UIView animateWithDuration:.25
                     animations:^{
                         // TODO: some animations on currentController and nextController
                     } completion:^(BOOL finished) {
                         [self.currentController wasMovedOffScreen];
                         self.currentController = nextController;
                     }];
}

Что касается вашей первоначальной проблемы, ARC хорошо знает, как обрабатывать блоки - если вы ее не используете, я могу спросить, не забыли ли вы скопировать блок, объявленный в другом месте, затем сохраненный, а затем переданный в качестве завершения обработчик. Так как это не так, и так как вы не смогли получить репродукцию ... Я предполагаю, что вы, возможно, используете бета-версию SDK - в последнее время в бета-версиях были некоторые ошибки ARC. Если это так, вы можете попробовать собрать с последним стабильным выпуском и посмотреть, получите ли вы лучшие результаты.

...