Ответ 1
NSKeyedArchiver
построен компанией Apple. Они управляют кодом, выполняемым во время выполнения unarchiveObjectWithData:
, поэтому они также контролируют управление ресурсами во время обработки исключений (что является источником проблем за исключениями в Objective-C).
Если они могут гарантировать, что между вашим вызовом unarchiveObjectWithData:
и точкой в коде, где они создают исключение, нет никакого внешнего кода (ни третьей стороны, ни вашего кода приложения), теоретически возможно безопасно использовать исключение, до тех пор, пока код вызова позаботится о правильной очистке.
Проблема заключается в том, что это предположение может быть не так: обычно используется NSKeyedArchiver
для сериализации пользовательских объектов. Обычно пользовательский класс реализует initWithCoder:
для чтения данных классов (используя методы архиватора, такие как decodeObjectForKey:
).
Если архиватор выбрасывает исключение в одном из этих методов, нет способа исправить обработку ресурсов для архиватора. Исключение будет выбрано через пользовательский объект initWithCoder:
. Архиватор не знает, есть ли что-нибудь для очистки, чем десериализованные объекты. Таким образом, в этом случае возникновение исключения означает, что процесс находится в опасном состоянии, и может возникнуть нежелательное поведение.
Относительно ваших вопросов:
Почему [NSKeyedArchiver не использует правильную обработку ошибок Cocoa]?
Только инженеры Apple, которые построили архиватор, знают. Я предполагаю, что обработка исключений и архивирование с ключом были построены примерно в одно и то же время (около 2001 года), и в этот момент еще не было ясно, что обработка исключений никогда не будет гражданином первого класса в Objective-C.
Правильно ли шаблон @try?
Ограничение предостережений, описанных выше, является правильным. Если код Apple правильно обрабатывает случаи исключения, и ваш собственный код сериализации делает то же самое, что и шаблон @try может быть правильным.
Тем не менее, очень сложно добиться полной корректности. Вы должны убедиться, что все исполняемые коды знают об исключениях и правильно ли их очищают.ARC, например не выполняет очистку исключений для локальных переменных и временных объектов по умолчанию (вам нужно включить -fobjc-arc-exceptions
для этого).
Кроме того, нет документации по безопасности исключений для аксессуаров свойств @synthesized (когда atomic
они могут протечь блокировку).
Вывод:
Существует множество тонких способов того, как исключения могут разрушать вещи. Это сложно и требует глубокого знания реализации всех задействованных частей для создания безопасного кода исключения в Objective-C.
Все это приводит к заключению. Если вы хотите обработать ошибки изящно при загрузке, возможно, поврежденных архивов и продолжить нормальное выполнение впоследствии: Не использовать NSKeyedArchiver
.