Публичная Swift-библиотека должна передавать доменные ошибки в Objective-C-код с устойчивыми кодами. Как смоделировать такую ошибку?
Используйте тип ошибки, соответствующий CustomNSError, и явно задайте errorDomain, errorCode и errorUserInfo. Это формирует предсказуемое представление Swift-ошибки как NSError для Objective-C-кода.
Код ошибки должен обозначать стабильную категорию сбоя, а дополнительные данные следует передавать через userInfo. Не используйте текст сообщения для программного распознавания ошибки.
В Objective-C ошибки традиционно представлены типом NSError, который содержит домен, числовой код и словарь дополнительных данных. Swift ввёл протокол Error, позволяющий описывать ошибки типами и вариантами перечислений, но сам по себе Error не требует домена или числового кода.
CustomNSError нужен как адаптер между этими двумя моделями: он позволяет Swift-типу явно определить, каким будет его представление при передаче в Foundation и Objective-C API.
Если библиотека не определит стабильный домен и коды, Objective-C-клиенту будет сложно надёжно классифицировать ошибки. Проверка текста сообщения хрупка: текст может измениться из-за локализации, исправления формулировки или изменения деталей сбоя.
Нельзя бездумно использовать данные конкретного экземпляра как код ошибки. Например, путь к файлу или идентификатор запроса описывает обстоятельства сбоя, но не должен создавать новую семантику кода для каждого значения.
Тип ошибки должен соответствовать CustomNSError. Его основные элементы:
errorDomain — постоянный идентификатор домена библиотеки;errorCode — стабильный числовой код категории ошибки;errorUserInfo — дополнительные данные, необходимые для диагностики или обработки.При приведении такой ошибки к NSError Foundation использует заданные домен, код и дополнительные данные. Objective-C-клиент может проверять домен и код, не зная внутреннего Swift-перечисления.
Коды следует считать частью публичного контракта: после выпуска библиотеки не переиспользуйте старый код для другой причины. Если нужно изменить внутреннюю структуру enum, внешние домен и коды можно сохранить прежними.
CustomNSError отвечает за структурированное представление ошибки, но не делает ошибки сравнимыми автоматически и не заменяет локализацию. Для пользовательского текста можно отдельно использовать механизмы Foundation, например LocalizedError; программная логика при этом должна опираться на домен и код.
Слой хранения Swift-библиотеки возвращает ошибку notFound(path:), а публичный API доступен из Objective-C. Рассматривались три варианта.
Первый — передавать строку сообщения. Это просто, но клиент не может надёжно отличить отсутствие файла от отказа в доступе после изменения текста или локализации.
Второй — вручную создавать NSError в каждом месте возникновения ошибки. Такой подход даёт контроль, но дублирует маппинг и повышает риск расхождения доменов, кодов и userInfo.
Третий — описать доменный Swift-тип через CustomNSError. Он централизует преобразование, сохраняет типобезопасную модель внутри библиотеки и предоставляет Objective-C стабильные значения.
Выбран третий вариант. В результате Swift-код работает с enum и associated values, а Objective-C-клиент получает единый домен, устойчивые коды и путь к файлу в userInfo.
1. Делает ли CustomNSError два экземпляра ошибки сравнимыми через ==?
Нет. Протокол задаёт мост к формату NSError, но не добавляет Equatable самому типу ошибки. Если сравнение необходимо внутри Swift, тип должен отдельно соответствовать Equatable, причём правила сравнения нужно определить для associated values.
Кроме того, сравнение NSError по домену и коду отвечает только на вопрос о категории ошибки. Два экземпляра с одинаковым кодом могут содержать разные диагностические данные в userInfo.
2. Что лучше помещать в errorCode, если ошибка содержит associated values?
В errorCode следует помещать стабильную категорию, например «объект не найден». Конкретный путь, идентификатор операции или внешний код сервера лучше передавать через errorUserInfo.
Такой расклад позволяет клиенту написать устойчивую проверку по домену и коду, не создавая отдельный код для каждого значения associated value. Если associated value меняет именно категорию ошибки, это обычно должно быть отдельным вариантом enum и, возможно, отдельным кодом.
3. Что произойдёт, если тип соответствует только Error, но не CustomNSError?
Ошибка всё равно может быть преобразована Foundation в NSError, однако библиотека не задаёт через CustomNSError собственный стабильный контракт домена, кода и дополнительных данных. На детали автоматически сформированного представления нельзя опираться как на публичный API библиотеки.
Если Objective-C-клиент должен программно различать причины сбоя, явная реализация CustomNSError предпочтительнее. Она документирует границу между внутренней моделью Swift-ошибки и внешним контрактом Foundation.