Использование NSException в приложениях для iPhone

StackOverflow https://stackoverflow.com/questions/4310560

  •  29-09-2019
  •  | 
  •  

Вопрос

Один из моих друзей попросил меня не использовать NSException в приложениях для iPhone.Причина, которую он привел, была "узким местом в производительности".Но я в этом не уверен.

Может ли кто-нибудь подтвердить мне, что мы должны воздержаться от использования NSException в приложении для iPhone?Если у вас есть рекомендации по использованию NSException, пожалуйста, укажите и это.

Обновить:

Это Ссылка просит нас использовать обработку исключений на уровне приложения.Кто-нибудь когда-нибудь делал это?Пожалуйста, опишите его преимущества и любые другие проблемы с производительностью, которые он может создать.

Это было полезно?

Решение

Короче:

Не используйте исключения, чтобы указать что-то, но неисправные ошибки

Только подходит для использования @ TRY / @ CALL, чтобы иметь дело с необработанными ошибками. Никогда не уместно использовать @ Throw / @ TRY / @ CALL, чтобы выполнить поток управления, как операции на iOS или Mac OS X. даже тогда, учитывайте внимательно, лучше ли вы используете исключение, чтобы указать необработанную ошибку или просто сбой ( вызов прерванию ()); Авария часто оставляет значительно больше доказательств.

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

Поведение любого исключения, брошенного через системный фондный код не определен.


Можете ли вы объяснить, что «поведение любого исключения, полученного через системную структуру, не определено». в деталях?

Конечно.

Системные рамки используют конструкцию, где любое исключение считается фатальным, невосстанавливаемым, ошибкой; Ошибка программиста для всех намерений и целей. Существует очень ограниченное количество исключений (хе) к этому правилу.

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

Рассмотрим этот стек вызовов:

your-code-1()
    system-code()
        your-code-2()

Т.е. код, где ваш код вызывает системный код, который вызывает больше вашего кода (очень распространенный шаблон, хотя стеки вызовов, очевидно, значительно глубже).

Если your-code-2 бросает исключение, что исключения проходят system-code означает, что поведение не определена; system-code Может или не может оставить ваше приложение в неопределенном, потенциально срочном или сболе данных, штат.

Или, более сильно: вы не можете сделать исключение в your-code-2 с ожиданием, что вы можете поймать и справиться с этим в your-code-1.

Другие советы

Я использовал обработку исключений для своих довольно интенсивных аудиоприложение без каких бы то ни было проблем.После долгого чтения и небольшого сравнительного анализа и дизассемблирования я пришел к противоречивому выводу, что нет реальной причины не использовать их (разумно) и достаточно причин не делать этого (NSError pointer-указатели, бесконечные условные обозначения ... фу!).Большая часть того, что люди говорят на форумах, просто повторяет документы Apple Docs.

Я вдаюсь в довольно подробные подробности в это сообщение в блоге но я изложу здесь свои выводы:

Миф 1:@try /@catch/@finally - это слишком дорого (с точки зрения процессора)

На моем iPhone 4 выбрасывание и перехват 1 миллиона исключений занимает около 8,5 секунд.Это составляет примерно всего 8,5 микросекунд на каждую.Дорого обходится в вашем потоке CoreAudio в реальном времени?Может быть, немного (но вы бы никогда не стали создавать исключения, не так ли ??), но задержка в 8,5 мкс в UIAlert, сообщающая пользователю о проблеме с открытием их файла, будет ли это замечено?

Миф 2:Блоки @try Имеют стоимость На 32-битной iOS

В документах Apple говорится о "блоках с нулевой стоимостью @try на 64-битный" и заявите, что 32-разрядность сопряжена с определенными затратами.Небольшой сравнительный анализ и дизассемблирование, по-видимому, указывают на то, что в 32-разрядной iOS (ARM-процессор) также существуют блоки @try с нулевой стоимостью.Имела ли Apple в виду 32-битный Intel?

Миф 3:Важно, что Исключения, создаваемые через фреймворки Cocoa, не определены

Да, они "не определены", но что вы вообще делаете, просматривая фреймворк Apple? Конечно Apple не обрабатывает их за вас. Весь смысл реализации обработки исключений для восстанавливаемых ошибок заключается в том, чтобы обрабатывать их локально - просто не каждую отдельную строку "локально".

Одним из крайних случаев здесь являются такие методы, как NSObject:performSelectorOnMainThread:waitUntilDone:.Если более поздний параметр равен YES, это действует как синхронная функция, и в этом случае вас могут простить за то, что вы ожидали, что исключение всплывет в вашу вызывающую область.Например:

/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCThread
/////////////////////////////////////////////////////////////////////////

@interface l5CCThread : NSThread @end

@implementation l5CCThread

- (void)main
{
    @try {

        [self performSelectorOnMainThread:@selector(_throwsAnException) withObject:nil waitUntilDone:YES];

    } @catch (NSException *e) {
        NSLog(@"Exception caught!");
    }
}
- (void)_throwsAnException { @throw [NSException exceptionWithName:@"Exception" reason:@"" userInfo:nil]; }

@end

/////////////////////////////////////////////////////////////////////////
#pragma mark - l5CCAppDelegate
/////////////////////////////////////////////////////////////////////////

@implementation l5CCAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    l5CCThread *thd = [[l5CCThread alloc] init];
    [thd start];

    return YES;
}
// ...

В этом случае исключение будет проходить "через cocoa framework" (цикл выполнения основного потока), пропуская ваш catch и приводя к сбою.Вы можете легко обойти это, используя GCD dispatch_synch и вводим в его блочный аргумент вызов метода плюс любую обработку исключений.

Зачем использовать NSException вместо NSError

Любой, кто когда-либо работал в одном из старых фреймворков на базе C, таких как Core Audio, знает, какая это рутинная работа - проверять, обрабатывать ошибки и сообщать о них.Основное преимущество, которое предоставляют @try/@catch и NSExceptions, заключается в том, что ваш код становится чище и проще в обслуживании.

Допустим, у вас есть 5 строк кода, которые работают с файлом.Каждая из них может выдавать одну из, скажем, 3-х различных ошибок (например, нехватка места на диске, ошибка чтения и т.д.).Вместо того, чтобы оборачивать каждую строку в условное выражение, которое проверяет отсутствие возвращаемого значения, а затем передает исследование указателя NSError другому методу ObjC (или, что еще хуже, использует #define макрос!), вы оборачиваете все 5 строк в один - единственный @попробуйте обработать каждую ошибку прямо там.Подумайте о строках, которые вы сэкономите!

Создавая подклассы NSException, вы также можете легко централизовать сообщения об ошибках и избежать переполнения ими вашего кода.Вы также можете легко отличить "нефатальные" исключения вашего приложения от фатальных ошибок программиста (например, NSAssert).Вы также можете избежать необходимости в константе "name" (именем подкласса является "name").

Примерами всего этого и более подробной информацией о тестах и разборке являются в этом посте в блоге...

Исключения плюс try / catch /finally - это парадигма, используемая практически во всех других основных языках (C ++, Java, PHP, Ruby, Python).Может быть, его время, чтобы отбросить паранойю и обнять его так же...по крайней мере в iOS.

Обычно спросите себя, пытаетесь ли вы сигнализировать об ошибке, или у вас действительно есть исключительное условие? Если первое, то это очень плохая идея независимо от какой -либо проблемы с производительностью, реальной или воспринимаемой. Если последнее, это определенно правильно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top