#iphone #objective-c #ios #exception
#iPhone #objective-c #iOS #исключение
Вопрос:
В моем проекте iOS (iPhone / cocos2d) я обнаружил, что исключения, которые я создаю сам, не приводят к завершению работы приложения (они просто вызывают завершение текущей функции, что приводит к странному поведению, зависшему наполовину). Например, следующий код вызывает сбой:
NSArray* testArray = [NSArray arrayWithObjects:@"One", @"Two", @"Three", nil];
[testArray objectAtIndex:400];
Когда я запускаю этот код, я получаю следующее в консоли, как и следовало ожидать:
2011-06-07 12:55:20.421 mansion-iphone[38184:207] *** Terminating app due to
uncaught exception 'NSRangeException', reason: '*** -[NSArray
objectAtIndex:]: index 400 beyond bounds [0 .. 2]'
Однако, если я пытаюсь вызвать исключение (например, из assert), я получаю половинную остановку, если я не включил «Остановить исключения Objective-C». Для меня это нормально, но вызывает проблемы, когда мои тестировщики сообщают о проблемах — поскольку приложение не зависало, у них нет журнала сбоев, чтобы отправить мне. Вот пример исключения, которое не работает:
NSException* e = [NSException exceptionWithName:NSInternalInconsistencyException
reason:[NSString stringWithFormat:@"%s %@", __PRETTY_FUNCTION__,
[NSString stringWithFormat:@"Invalid argument"]] userInfo:nil];
[e raise];
Если «Остановить исключения Objective-C» отключено, это даже не вызывает сообщения на консоль — использование NSAssert вместо этого выдает мне сообщение консоли, но по-прежнему не останавливает. Итак, похоже, что исключения, сгенерированные классами Cocoa, ведут себя правильно, но исключения, созданные из моего кода, — нет.
Я проверил свой код и cocos2d и не нашел никаких блоков @try, которые, казалось бы, предотвращали исключение; у кого-нибудь есть идея?
Ответ №1:
Пользовательское исключение должно работать так же, как и другие исключения, и я смог убедиться в этом в моем собственном тестовом приложении. Некоторые вещи, которые нужно проверить:
- Убедитесь, что
NSSetUnhandledExceptionHandler
не вызывается, чтобы перехватить все необработанные исключения. - Попробуйте запустить свое приложение вне отладчика.
- Я протестировал ваш код выше, и мое приложение завершается, как и ожидалось, когда возникает исключение NSRangeException или пользовательское исключение NSException, но оно не обрабатывается.
- Попробуйте вызвать ваше исключение в другом месте, чтобы убедиться, что оно работает, например, в main ().
ПРИМЕЧАНИЕ: Не используйте исключения как способ управления потоком программы, поскольку они очень дороги, когда создаются в Objective-C.
Комментарии:
1. Привет, спасибо за твой ответ. Вы знаете, я не думал пробовать этот блок кода прямо внутри моего метода applicationDidFinishLaunching: , но это приводит к сбою приложения, как и ожидалось. Однако при дальнейшем внедрении в приложение (это игра, использующая библиотеку Cocos2d) то же исключение ничего не делает; мне придется провести дополнительные исследования.
2. Я также заметил, что в документах Apple говорится следующее: «Исключения в главном потоке приложения Cocoa обычно не достигают уровня обработчика неперехваченных исключений, потому что глобальный объект приложения улавливает все такие исключения». Полезно знать, хотя, опять же, иногда это работает — Я думаю, это «обычно».
3. * … они очень дорогие … » Стоимость в этом контексте не вызывает беспокойства. Их действительно не так дорого использовать. Стоимость такая же, как при создании исключения C . Реальная проблема IMO заключается в том, что программы ObjC просто не разработаны / написаны для восстановления после исключений. Использование исключений в качестве потока управления обычно приводит ко многим утечкам и другим подобным проблемам, связанным с тем, что очистка не происходит при развертывании. Другой пример:
@synchronized
будет правильно разматываться и разблокироваться, но я просто не вижу, чтобы разработчики ObjC действительно очищали другие механизмы блокировки вручную при разматывании.