Avatar ·

Как в Swift сделать заглавной только первую букву строки?

Всем привет! Я недавно начал изучать Swift и столкнулся с такой проблемой. Мне нужно преобразовать строку так, чтобы первая буква была заглавной, а все остальные — строчными. Например, из строки "hello WORLD" должно получиться "Hello world". Я знаю, что есть метод `.uppercased()` для всей строки и `.lowercased()` для преобразования в нижний регистр, но как применить их только к первой букве? Пробовал такой код: ```swift let str = "hello WORLD" let firstLetter = str.prefix(1).uppercased() let rest = str.dropFirst().lowercased() let result = firstLetter + rest print(result) // "Hello world" ``` Вроде бы работает, но я не уверен, что это правильный подход. Есть ли более элегантный способ? Может быть, в Swift есть специальный метод для этого? Вопрос возник, когда я писал приложение для iOS 8 (расширение), и мне нужно было форматировать имена пользователей, чтобы они выглядели аккуратно. Буду благодарен за любые советы и примеры кода! ОС: iOS 8+, Xcode 6.3, Swift 1.2 (но хотелось бы решение, которое работает и в новых версиях). <<>>

Правильный способ сделать первую букву заглавной в Swift

Ваш подход абсолютно верный! Давайте разберем его и рассмотрим несколько улучшенных вариантов, включая поддержку локалей и работу с новыми версиями Swift.

Базовое решение (Swift 1.2+ и выше)

let str = "hello WORLD"
let result = str.prefix(1).uppercased() + str.dropFirst().lowercased()
print(result) // "Hello world"

Этот код работает во всех версиях Swift, начиная с 1.2. Он:

  • Берет первый символ с помощью prefix(1) и делает его заглавным через uppercased()
  • Удаляет первый символ с помощью dropFirst() и делает остаток строчным через lowercased()
  • Объединяет обе части

Продвинутое решение с поддержкой локализации (Swift 3+ и выше)

extension String {
    func capitalizeFirstLetter() -> String {
        guard let first = first else { return self }
        return first.uppercased() + dropFirst().lowercased()
    }
}

// Использование:
let str = "hello WORLD"
print(str.capitalizeFirstLetter()) // "Hello world"

Это расширение добавляет метод capitalizeFirstLetter() к типу String. Оно безопасно обрабатывает пустые строки с помощью guard.

Учет локали (Swift 4+ и выше)

extension String {
    func capitalizeFirstLetter(with locale: Locale? = nil) -> String {
        guard let first = first else { return self }
        return String(first).uppercased(with: locale) + dropFirst().lowercased(with: locale)
    }
}

// Пример с турецкой локалью (где i → İ)
let turkishStr = "istanbul"
print(turkishStr.capitalizeFirstLetter(with: Locale(identifier: "tr_TR"))) 
// "İstanbul" (правильно для турецкого языка)

Обработка Unicode и эмодзи

extension String {
    func capitalizeFirstLetterUnicode() -> String {
        guard let first = unicodeScalars.first else { return self }
        let upperFirst = String(first).uppercased()
        let rest = String(unicodeScalars.dropFirst())
        return upperFirst + rest.lowercased()
    }
}

// Пример с эмодзи:
let emojiStr = "👋hello"
print(emojiStr.capitalizeFirstLetterUnicode()) // "👋Hello" (эмодзи не меняется)

Важные замечания для iOS 8 (Swift 1.2)

В вашем случае для iOS 8 лучше использовать самый простой вариант:

let str = "hello WORLD"
let result = (str as NSString).substringToIndex(1).uppercaseString + 
             (str as NSString).substringFromIndex(1).lowercaseString

Этот код использует NSString, который доступен во всех версиях iOS. Однако в современных проектах рекомендую использовать Swift-native подходы, описанные выше.

Почему ваш код правильный?

  • Производительность: prefix(1) и dropFirst() работают за O(1) для строк с латиницей
  • Безопасность: корректно обрабатывает пустые строки и однобуквенные строки
  • Unicode-совместимость: работает с любыми символами, включая акценты и эмодзи

Единственное, что можно улучшить — добавить обработку nil (если строка опциональная) и локализацию для разных языков. Но для большинства задач ваше решение — золотой стандарт.

<<>>

Альтернативный подход: метод capitalized с настройкой

В Swift есть встроенный метод capitalized, который делает заглавной первую букву каждого слова. Но его можно адаптировать под нашу задачу:

let str = "hello WORLD"
let result = str.lowercased().capitalized
print(result) // "Hello World"

Внимание: этот метод делает заглавной первую букву каждого слова, а не только первого. Если ваша строка содержит несколько слов, результат будет отличаться от желаемого. Например, "hello beautiful WORLD" превратится в "Hello Beautiful World", а не "Hello beautiful world".

Когда это подходит?

  • Для одиночных слов (имена, названия)
  • Когда нужно капитализировать каждое слово (например, для заголовков)
  • В простых случаях, где не важна точность форматирования

Более точная версия с использованием регулярных выражений

extension String {
    func capitalizeFirstOnly() -> String {
        return replacingOccurrences(
            of: "^.", 
            with: String(prefix(1)).uppercased(), 
            options: .regularExpression
        )
    }
}

let str = "hello WORLD"
print(str.lowercased().capitalizeFirstOnly()) // "Hello world"

Этот подход использует регулярное выражение для замены первого символа. Он менее производительный, чем решение с prefix/dropFirst, но может быть полезен в некоторых сценариях.