Как преобразовать строку (String) в число с плавающей точкой (Double) в Swift?
Основной способ: инициализатор Double(String)
В Swift для преобразования строки в Double используется инициализатор Double(_:). Однако он возвращает опциональное значение (Double?), так как строка может не содержать корректного числа. Вот правильный базовый пример:
let priceString = "12.50"
if let price = Double(priceString) {
print("Цена: \(price)") // Выведет: Цена: 12.5
} else {
print("Некорректное значение")
}
Обработка разных форматов чисел
Если строка может содержать запятую вместо точки (например, "12,50"), Double() не сработает напрямую. Нужно заменить запятую на точку:
let priceString = "12,50"
let normalizedString = priceString.replacingOccurrences(of: ",", with: ".")
if let price = Double(normalizedString) {
print("Цена: \(price)") // 12.5
} else {
print("Некорректное значение")
}
Удаление лишних символов
Часто пользователи вводят пробелы, символы валюты или буквы. Лучше очистить строку перед преобразованием:
let dirtyString = " $ 12.50 USD "
let cleanedString = dirtyString
.trimmingCharacters(in: .whitespaces)
.components(separatedBy: CharacterSet.decimalDigits.inverted)
.joined()
// cleanedString = "1250" — удалили всё, кроме цифр и точки
// Но это удалит и десятичную точку! Лучше использовать другой подход:
let filteredString = dirtyString
.trimmingCharacters(in: .whitespaces)
.filter { "0123456789.,".contains($0) }
.replacingOccurrences(of: ",", with: ".")
// filteredString = "12.50"
if let price = Double(filteredString) {
print("Цена: \(price)") // 12.5
}
Использование NumberFormatter для локализации
Если ваше приложение поддерживает разные локали (например, в Европе используют запятую как десятичный разделитель), лучше использовать NumberFormatter:
let priceString = "12,50"
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.locale = Locale(identifier: "de_DE") // Немецкая локаль с запятой
if let number = formatter.number(from: priceString) {
let price = number.doubleValue
print("Цена: \(price)") // 12.5
} else {
print("Некорректное значение")
}
Обработка ошибок с помощью guard
Для более чистого кода используйте guard:
func parsePrice(from string: String) -> Double? {
let cleaned = string
.trimmingCharacters(in: .whitespaces)
.replacingOccurrences(of: ",", with: ".")
guard let price = Double(cleaned) else {
print("Ошибка: '\(string)' не является числом")
return nil
}
return price
}
if let price = parsePrice(from: " 12,50 ") {
print("Успех: \(price)")
}
Рекомендации
- Всегда проверяйте результат преобразования через
if letилиguard - Не используйте принудительное извлечение (
!) — это приведёт к крашу - Для пользовательского ввода используйте
NumberFormatterс учётом локали - Удаляйте лишние символы, но аккуратно: не удалите точку или запятую
Эти методы покрывают 99% случаев преобразования строк в Double в Swift.
<<Альтернативный подход: использование Scanner
Класс Scanner (ранее NSScanner) позволяет более гибко парсить числа из строк, особенно если строка содержит несколько значений или сложный формат:
let input = "Цена: 12.50 долларов"
let scanner = Scanner(string: input)
var scannedValue: Double = 0
// Игнорируем нечисловые символы в начале
scanner.charactersToBeSkipped = CharacterSet.decimalDigits.inverted
if scanner.scanDouble(&scannedValue) {
print("Найдено число: \(scannedValue)") // 12.5
} else {
print("Число не найдено")
}
Почему это может быть удобно?
- Scanner автоматически пропускает пробелы и нечисловые символы
- Позволяет извлечь число из середины строки без дополнительной очистки
- Поддерживает разные локали через свойство
locale
Недостатки
Scanner — это Objective-C класс, поэтому его использование в Swift может выглядеть менее "свифтово". Для простых случаев достаточно Double() или NumberFormatter.