Avatar ·

Как преобразовать строку (String) в число с плавающей точкой (Double) в Swift?

Всем привет! Я только начал изучать Swift и столкнулся с проблемой при работе с числами. У меня есть текстовое поле, в которое пользователь вводит цену товара, и мне нужно преобразовать эту строку в Double для дальнейших расчетов. Вот мой код: ```swift let priceString = "12.50" let priceDouble = Double(priceString) // Здесь возникает ошибка ``` Я читал, что можно использовать `Double()`, но в результате получаю `nil` или ошибку компиляции. Я пробовал разные варианты, но ничего не работает. Подскажите, как правильно преобразовать строку в Double? Что делать, если строка содержит не только цифры, но и буквы? Например, пользователь может ввести "12,50" вместо "12.50" (с запятой вместо точки). Как обработать такие случаи? Буду благодарен за примеры кода и объяснение, как избежать краша приложения, если преобразование невозможно. Заранее спасибо! <<>>

Основной способ: инициализатор 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.