Лечу Crash'и NSLog'ами. Недорого. Многолетний опыт. 100% гарантия.
Примерно таким заголовком можно было бы описать то, что три с половиной месяца назад происходило у меня на одном из проектов. Вернее, это даже был не мой проект, но с проблемой crash'а пришлось разбираться именно мне.
Все началось с того, что на одном из относительно больших проектов начало стабильно вываливаться исключение при авторизации пользователя. «Ну и что тут такого? У всех бывает. Проверку на nil забыли поставить или где-то накосячили. „Тоже, мне, большое событие — crash на проекте“, — подумает большая часть программистов. В принципе — абсолютно согласен. Crash — не такое уж и редкое явление в программировании под iPhone, и с ним сталкиваешься по десять раз на день. Но этот был особенным. От него уже начало попахивать „магией“, когда мне сказали про его некоторые параметры и особенности:
- Воспроизводимость на симуляторе: 100%
- Воспроизводимость на устройстве: 0%
- Путь к крэшу (после локализации крэша): ~ 40 секунд
- Настройки оптимизации при компиляции (-O1,-O2...) не влияют на воспроизводимость
- XIB'ы в проекте не используются
Да выглядел он довольно безобидно:
// Code
UITextView * textView = [ [UITextView alloc] initWithFrame:CGRectMake(0, 150, _width, _height)];
// Exception
*** Terminating app due to uncaught exception 'CALayerInvalidGeometry',
reason: 'CALayer bounds contains NaN: [0 0; nan 200]'
»Ну тут же и ежу понятно, что width — после вычисления — NaN!", — подумал я. Бегло поглядев где и как вычисляется ширина вьюхи, и не найдя ничего особого опасного, я, для утверждения своей догадки, поставил перед созданием вьюхи NSLog. А вдобавок, и точку останова на строке с созданием элемента.
// Source:
NSLog(@"width = %f", _width);
//Output:
width = 200
«Гм», — подумал про себя я, и продолжил выполнение программы после точки останова. И крэша не произошло…