Я провел день, работая над странной ошибкой в своем приложении для iOS 5 для iPad, и мне было интересно, есть ли у кого-нибудь какая-нибудь информация.
Вот общая настройка: есть подкласс UIViewController StoryViewChildController, который имеет две переменные-члены: _currentModel
и _comingModel
. В StoryViewChildController есть метод, который вызывает [[INEWSStoryModel alloc] init]
и возвращает созданный результирующий объект. Во время viewDidLoad
у меня есть следующий блок кода. Обратите внимание, что это не дословно скопировано из кода - это более сложно - но я пытаюсь подвести итог:
_currentModel = [self createModel];
_comingModel = [self createModel];
Затем, в какой-то момент, я должен иметь возможность поменять местами _currentModel и _comingModel вместе с другими объектами. Вот метод обмена, дословно из моего кода:
- (void)swapComingPageAndCurrentPage {
[_swapLock lock];
//Swap story views
IPCStoryView *swapPage = _currentPage;
_currentPage = _comingPage;
_comingPage = swapPage;
//Swap models
INEWSStoryModel *swapModel = _currentModel;
_currentModel = _comingModel;
_comingModel = swapModel;
//Swap players
PlayerController *swapPlayer = _currentPlayerController;
_currentPlayerController = _comingPlayerController;
_comingPlayerController = swapPlayer;
// clear out the content of the old view
[_comingPage resetStoryView];
[_comingPlayerController resetPlayer];
_comingPlayerController.view.alpha = 0.0;
_currentPageURI = _lastRequestedStory;
[_swapLock unlock];
}
Проблема в том, что когда я запускаю свой проект в конфигурации выпуска (которая использует -O для оптимизации компилятора), происходит сбой во время обмена объектами модели. Авария происходит из-за попытки получить доступ к объекту Zombie. Я использовал Инструменты, чтобы отследить путь сохранения / освобождения моих объектов, и, входя в этот метод, _currentModel имеет счетчик ссылок 1, как и ожидалось. Однако строка INEWSStoryModel *swapModel = _currentModel;
НЕ приводит к вызову сохранения в _currentModel, поэтому при следующем вызове _currentModel = _comingModel;
число ссылок уменьшается до 0. Затем, когда swapModel
выходит из области действия, другой вызов освобождения попытался, и программа вылетает.
Мне почти кажется, что оптимизация компилятора оптимизирует сохранение вызовов, которые не следует делать. У кого-нибудь еще была такая проблема? Могу ли я сделать что-то еще не так? При необходимости могу выложить больше кода из класса.
Другие интересные примечания: если я установлю переменную swapModel как __autoreleasing, код будет работать. Кроме того, если я добавляю следующий блок кода в конце метода подкачки, код работает:
_comingPage.cueView.frame = [_comingPage adjustCueViewFrame:_comingPage.cueView.frame
ForVideoShowing: NO
inOrientation:_currentOrientation];
Все, что делает этот метод, это настраивает фрейм UIView. Тот факт, что я могу добавить несвязанный код в конец метода и не создавать зомби, заставляет меня думать, что компилятор неправильно оптимизирует. У кого-нибудь есть идеи?