Как обрабатывать ошибки при работе с числами и строками в Swift
Что проверяют
Различаете ли вы три механизма Swift: опционалы, выбрасываемые ошибки и аварийную остановку (trap). Интервьюеру важно, знаете ли вы, что переполнение Int не ловится через do-catch. Следом часто спрашивают про разбор числа из поля ввода с учётом локали.
Как отвечать
Разделите источники ошибок.
Строка в число: Int("42") возвращает опционал, и на "abc", " 42" с пробелом или "12.5" вы получите nil, а не исключение. Double("3,14") тоже nil: этот инициализатор понимает только точку и от локали не зависит. Для пользовательского ввода берите NumberFormatter или FormatStyle, например try Double(text, format: .number): он учитывает локаль и выбрасывает ошибку. Для денег Decimal, а не Double.
Арифметика:
- переполнение:
Int.max + 1аварийно останавливает приложение. Безопасно черезaddingReportingOverflow(_:)иmultipliedReportingOverflow(by:), осознанное переполнение через&+; - деление на ноль: у целых это trap, у
Doubleполучитсяinfилиnan, проверяйтеisFinite; - конвертация:
Int(someDouble)падает наnanи слишком больших значениях, аInt(exactly:)вернётnil.
Строки: индекс это String.Index, а не Int. Выход за границу роняет приложение, поэтому смещение берут через index(_:offsetBy:limitedBy:), он вернёт опционал. String(data:encoding:) тоже опционален.
Когда причину нужно донести наверх, заведите свой enum ParseError: Error и бросайте его через throws, в Swift 6 тип можно указать явно: throws(ParseError). На границе с интерфейсом ошибку переводят в понятный пользователю текст.
Где спотыкаются
Оборачивают арифметику в do-catch и думают, что переполнение будет поймано. catch ловит только брошенные ошибки, trap роняет приложение.
Разбирают ввод через Double(text) и получают nil у пользователя с русской локалью, который пишет запятую.
Ставят Int(text)! или try! там, куда приходят данные извне, либо глушат всё через try? и теряют причину: пользователь видит пустое поле без объяснения.