Swift stosuje .uppercaseString tylko do pierwszej litery ciągu


232

Próbuję stworzyć system autokorekty, a gdy użytkownik wpisze słowo z wielką literą, autokorekta nie działa. Aby to naprawić, zrobiłem kopię napisanego łańcucha, zastosowałem .lowercaseString, a następnie porównałem je. Jeśli ciąg znaków jest rzeczywiście źle wpisany, powinien poprawić słowo. Jednak słowo, które zastępuje wpisane słowo, jest pisane małymi literami. Więc muszę zastosować .uppercaseString tylko do pierwszej litery. Początkowo myślałem, że mogę użyć

nameOfString[0]

ale to najwyraźniej nie działa. Jak uzyskać pierwszą literę ciągu na wielkie litery, a następnie móc wydrukować cały ciąg z wielką literą pierwszej litery?

Dzięki za wszelką pomoc!

Odpowiedzi:


512

W tym mutujące i niemutujące wersje zgodne z wytycznymi API.

Swift 3:

extension String {
    func capitalizingFirstLetter() -> String {
        let first = String(characters.prefix(1)).capitalized
        let other = String(characters.dropFirst())
        return first + other
    }

    mutating func capitalizeFirstLetter() {
        self = self.capitalizingFirstLetter()
    }
}

Swift 4:

extension String {
    func capitalizingFirstLetter() -> String {
      return prefix(1).uppercased() + self.lowercased().dropFirst()
    }

    mutating func capitalizeFirstLetter() {
      self = self.capitalizingFirstLetter()
    }
}

3
Tylko uwaga, że .capitalizedStringnie działa już w Xcode 7 Beta 4. Ciągi zmieniły się nieco w Swift 2.0.
kakubei

2
@Kirsteins: masz rację, mój zły. Zapomniałem importować Foundation owczy uśmiech
kakubei

3
@LoryLory Użyj .uppercaseStringdo tego
Kirsteins,

2
To jest naprawdę skuteczna odpowiedź kolega .. Praca z Xcode 7.1.1 / Swift 2.1 .... Dzięki :)
onCompletion

20
to właśnie .capitalizedteraz. Zauważ teżcapitalizedStringWith(_ locale:)
Raphael

152

Swift 5.1 lub nowszy

extension StringProtocol {
    var firstUppercased: String { prefix(1).uppercased() + dropFirst() }
    var firstCapitalized: String { prefix(1).capitalized + dropFirst() }
}

Szybki 5

extension StringProtocol {
    var firstUppercased: String { return prefix(1).uppercased() + dropFirst() }
    var firstCapitalized: String { return prefix(1).capitalized + dropFirst() }
}

"Swift".first  // "S"
"Swift".last   // "t"
"hello world!!!".firstUppercased  // "Hello world!!!"

"DŽ".firstCapitalized   // "Dž"
"Dž".firstCapitalized   // "Dž"
"dž".firstCapitalized   // "Dž"

3
Dobra robota. Zredagowałem mój, aby najpierw przekazać małe litery, i przemianowałem go na Właściwy.
ericgu,

Podoba mi się szybkie rozwiązanie 2.1.1, ale kiedy uruchamiam aplikację i sprawdzam, czy nie ma wycieków, pokazuje, że przecieka.
Henny Lee,

1
Właśnie stworzyłem nowy projekt i wygląda na to, że powoduje wyciek pamięci, gdy jest on używany razem z UITextFieldobserwatorem UITextFieldTextDidChangeNotification.
Henny Lee

@Henry nie ma to nic wspólnego z samym kodem. jeśli wystąpią jakiekolwiek problemy z wydajnością / pamięcią, należy zgłosić to firmie Apple.
Leo Dabus

1
@LeoDabus Wydaje mi się, że to zależy od tego, który z nich czyni intencje kodu bardziej widocznymi. Być może najlepszy jest dosłowny ciąg pustych liter.
Nicolas Miari

84

Swift 3.0

za „Hello World”

nameOfString.capitalized

lub „HELLO WORLD”

nameOfString.uppercased

3
Charlesism odpowiedział już wersją Swift 3 dwa miesiące temu ...
Eric Aya

11
Spowoduje to zapisanie pierwszego znaku każdego słowa ciągu, a nie tylko pierwszego słowa.
Bocaxica,

Zwraca: wielka kopia łańcucha. public func wielkie litery () -> String Swift 3.0 lub dla „HELLO WORLD” nameOfString.uppercased INSTEAD OF ABOVE nameOfString.uppercased ()
Azharhussain Shaikh

40

Swift 4.0

string.capitalized(with: nil)

lub

string.capitalized

Jednak litera każdego słowa jest wielką literą

Dokumentacja Apple:

Łańcuch wielkich liter to ciąg z pierwszym znakiem w każdym słowie zmienionym na odpowiadającą mu wielką literę, a wszystkie pozostałe znaki ustawione na odpowiadające im małe litery. „Słowo” to dowolna sekwencja znaków rozdzielona spacjami, tabulatorami lub znakami końca linii. Niektóre popularne słowa interpunkcyjne ograniczające nie są brane pod uwagę, więc ta właściwość może na ogół nie dawać pożądanych wyników dla ciągów wielowątkowych. Zobacz metodę getLineStart (_: end: contentEnd: for :), aby uzyskać dodatkowe informacje.


1
Nie mam pojęcia, dlaczego ludzie nie są otwarci na tę odpowiedź. Jeśli ludzie chcą tylko pierwszego słowa pisanego wielkimi literami, mogą pobrać pierwsze i napisać je najłatwiej dzięki własności pisanej wielkimi literami.
ScottyBlades,

1
Co ważne, „wielkie litery” są poprawne dla wszystkich znaków Unicode, podczas gdy użycie „wielkich liter” dla pierwszego znaku nie jest.
gnasher729,

23
extension String {
    func firstCharacterUpperCase() -> String? {
        let lowercaseString = self.lowercaseString

        return lowercaseString.stringByReplacingCharactersInRange(lowercaseString.startIndex...lowercaseString.startIndex, withString: String(lowercaseString[lowercaseString.startIndex]).uppercaseString)
    }
}

let x = "heLLo"
let m = x.firstCharacterUpperCase()

W przypadku Swift 5:

extension String {
    func firstCharacterUpperCase() -> String? {
        guard !isEmpty else { return nil }
        let lowerCasedString = self.lowercased()
        return lowerCasedString.replacingCharacters(in: lowerCasedString.startIndex...lowerCasedString.startIndex, with: String(lowerCasedString[lowerCasedString.startIndex]).uppercased())
    }
}

To najlepsza odpowiedź IMO - upraszcza wszystkie przyszłe sprawy.
Robert

Nie trzeba sprawdzać, czy ciąg isEmptyi zainicjować ciąg, aby zastąpić oba. Możesz po prostu rozpakować pierwszą postać, a w przypadku jej niepowodzenia zwróć zero. Można to uprościć jakovar firstCharacterUpperCase: String? { guard let first = first else { return nil } return lowercased().replacingCharacters(in: startIndex...startIndex, with: first.uppercased()) }
Leo Dabus

17

Dla pierwszego znaku w użyciu słowa .capitalizedw trybie szybkim i do użycia całego słowa.uppercased()


10

Swift 2.0 (pojedyncza linia):

String(nameOfString.characters.prefix(1)).uppercaseString + String(nameOfString.characters.dropFirst())

1
Pozytywne. Zakłada się jednak, że wszystkie oryginalne ciągi znaków są małe. Dodałem .localizedLowercaseStringna końcu, aby działało z ciągami takimi jak: aNYsTring. String(nameOfString.characters.prefix(1)).uppercaseString + String(nameOfString.characters.dropFirst()).localizedLowercaseString
oyalhi

4

Swift 3 (xcode 8.3.3)

Wielkie litery wszystkich pierwszych znaków ciągu

let str = "your string"
let capStr = str.capitalized

//Your String

Wielkie litery wszystkich znaków

let str = "your string"
let upStr = str.uppercased()

//YOUR STRING

Wielkie litery tylko pierwszy znak ciągu

 var str = "your string"
 let capStr = String(str.characters.prefix(1)).uppercased() + String(str.characters.dropFirst())

//Your string

Nie spowoduje to użycia tylko pierwszego znaku ciągu
Rool Paap


3

Dostaję pierwszą postać powieloną z rozwiązaniem Kirsteinsa. Spowoduje to wielkie litery pierwszej postaci, bez podwójnego:

var s: String = "hello world"
s = prefix(s, 1).capitalizedString + suffix(s, countElements(s) - 1)

Nie wiem, czy jest bardziej czy mniej wydajny, po prostu wiem, że daje mi pożądany efekt.


Możesz sprawdzić, czy wielkie litery pierwszego znaku zmieniają ten znak - zapisując go we własnej stałej, a następnie testując równość z nowym ciągiem „wielkich liter”, a jeśli są one takie same, masz już to, czego chcesz.
David H

Twój post zainspirował tę odpowiedź - dzięki !: func capitaizeFirstChar (var s: String) -> String {if s.isEmpty == false {let range = s.startIndex ... s.startIndex let original = s.substringWithRange (zakres) let capitalized = original.capitalizedString if original == capitalized {return s} s.replaceRange (zakres, z: capitalized)} return s}
David H

1
W nowszych wersjach Swift countElementsjest po prostu count.
George Poulos,

3

Z Swift 3 możesz łatwo korzystać textField.autocapitalizationType = UITextAutocapitalizationType.sentences


3

Oto wersja dla Swift 5, która korzysta z interfejsu API właściwości skalarnych Unicode, aby ratować, jeśli pierwsza litera jest już wielka lub nie ma pojęcia wielkości liter:

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

Nie ma potrzeby inicjowania ciągu z pierwszym znakiem. return first.uppercased() + dropFirst()lub jeden liniowiec(first?.uppercased() ?? "") + dropFirst()
Leo Dabus

2

Wpisz pierwszy znak w ciągu

extension String {
    var capitalizeFirst: String {
        if self.characters.count == 0 {
            return self

        return String(self[self.startIndex]).capitalized + String(self.characters.dropFirst())
    }
}

2

W Swift 3.0 (jest to trochę szybsze i bezpieczniejsze niż zaakceptowana odpowiedź):

extension String {
    func firstCharacterUpperCase() -> String {
        if let firstCharacter = characters.first {
            return replacingCharacters(in: startIndex..<index(after: startIndex), with: String(firstCharacter).uppercased())
        }
        return ""
    }
}

nameOfString.capitalized nie będzie działać , będzie używać wielkich liter każdego słowa w zdaniu


1

Kredyty dla Leonardo Savio Dabus:

Wyobrażam sobie, że większość przypadków użycia polega na uzyskaniu odpowiedniej obudowy:

import Foundation

extension String {

    var toProper:String {
        var result = lowercaseString
        result.replaceRange(startIndex...startIndex, with: String(self[startIndex]).capitalizedString)
        return result
    }
}

1

Moje rozwiązanie:

func firstCharacterUppercaseString(string: String) -> String {
    var str = string as NSString
    let firstUppercaseCharacter = str.substringToIndex(1).uppercaseString
    let firstUppercaseCharacterString = str.stringByReplacingCharactersInRange(NSMakeRange(0, 1), withString: firstUppercaseCharacter)
    return firstUppercaseCharacterString
}

To nie jest szybkie.
Abhishek Bedi

1

Uwzględniając powyższe odpowiedzi, napisałem małe rozszerzenie, które zawiera pierwszą literę każdego słowa (ponieważ właśnie tego szukałem i pomyślałem, że ktoś inny może go użyć).

Pokornie składam:

extension String {
    var wordCaps:String {
        let listOfWords:[String] = self.componentsSeparatedByString(" ")
        var returnString: String = ""
        for word in listOfWords {
            if word != "" {
                var capWord = word.lowercaseString as String
                capWord.replaceRange(startIndex...startIndex, with: String(capWord[capWord.startIndex]).uppercaseString)
                returnString = returnString + capWord + " "
            }
        }
        if returnString.hasSuffix(" ") {
            returnString.removeAtIndex(returnString.endIndex.predecessor())
        }
        return returnString
    }
}

1
Swift String ma metodę o nazwie capitalizedString. Jeśli chcesz zastosować go do szeregu ciągów, sprawdź tę odpowiedź stackoverflow.com/a/28690655/2303865
Leo Dabus

1

Szybki 4

func firstCharacterUpperCase() -> String {
        if self.count == 0 { return self }
        return prefix(1).uppercased() + dropFirst().lowercased()
    }

0

Oto jak to zrobiłem małymi krokami, jest podobny do @Kirsteins.

func capitalizedPhrase(phrase:String) -> String {
    let firstCharIndex = advance(phrase.startIndex, 1)
    let firstChar = phrase.substringToIndex(firstCharIndex).uppercaseString
    let firstCharRange = phrase.startIndex..<firstCharIndex
    return phrase.stringByReplacingCharactersInRange(firstCharRange, withString: firstChar)
}

0
func helperCapitalizeFirstLetter(stringToBeCapd:String)->String{
    let capString = stringToBeCapd.substringFromIndex(stringToBeCapd.startIndex).capitalizedString
    return capString
}

Działa również po prostu przekaż swój ciąg i odzyskaj wielką literę.


0

Aktualizacja Swift 3

replaceRangeFunc jest terazreplaceSubrange

nameOfString.replaceSubrange(nameOfString.startIndex...nameOfString.startIndex, with: String(nameOfString[nameOfString.startIndex]).capitalized)

zmieniono nazwę metody capitalizedString na wielką
Rool Paap

0

Jestem częściowo zwolennikiem tej wersji, która jest oczyszczoną wersją z innej odpowiedzi:

extension String {
  var capitalizedFirst: String {
    let characters = self.characters
    if let first = characters.first {
      return String(first).uppercased() + 
             String(characters.dropFirst())
    }
    return self
  }
}

Stara się być bardziej efektywny, oceniając tylko samopodobne postacie, a następnie używa spójnych formularzy do tworzenia podłańcuchów.


0

Swift 4 (Xcode 9.1)

extension String {
    var capEachWord: String {
        return self.split(separator: " ").map { word in
            return String([word.startIndex]).uppercased() + word.lowercased().dropFirst()
        }.joined(separator: " ")
    }
}

String ma już właściwość nazwaną capitalizedwłaśnie w tym celu
Leo Dabus

0

Jeśli chcesz wielkie litery każdego słowa ciągu, możesz użyć tego rozszerzenia

Swift 4 Xcode 9.2

extension String {
    var wordUppercased: String {
        var aryOfWord = self.split(separator: " ")
        aryOfWord =  aryOfWord.map({String($0.first!).uppercased() + $0.dropFirst()})
        return aryOfWord.joined(separator: " ")
    }
}

Używany

print("simple text example".wordUppercased) //output:: "Simple Text Example"

2
po prostu użyj.capitalized
kakubei

0

Jeśli ciąg zawiera wszystkie wielkie litery, zadziała poniższa metoda

labelTitle.text = remarks?.lowercased().firstUppercased

To rozszerzenie ci pomoże

extension StringProtocol {
    var firstUppercased: String {
        guard let first = first else { return "" }
        return String(first).uppercased() + dropFirst()
    }
}

1
po prostu użyj.capitalized
kakubei

@kakubei Dlaczego głosujesz negatywnie. Ta metoda dotyczy przypadku Zdania. Wielkie litery zrobią każdy pierwszy znak słowa na kapitał. Przykładowy ciąg: - (TO JEST CHŁOPIEC) .capitalizedzwróci (To chłopiec) i ta metoda zwróci (To chłopiec) Oba są różne. (Proszę zrobić + ve Głosuj lub Usuń negatywne)
Ashu

Masz rację @ashu, przepraszam. Jednak nie mogę głosować, dopóki nie wyedytujesz odpowiedzi, więc może po prostu dokonaj niewielkiej edycji białych znaków i będę ją głosować. Jeszcze raz przepraszam.
kakubei

Nie ma potrzeby inicjowania ciągu z pierwszym znakiem. return first.uppercased() + dropFirst()lub powrót jednego liniowca(first?.uppercased() ?? "") + dropFirst()
Leo Dabus

0

Dodaj ten wiersz w metodzie viewDidLoad ().

 txtFieldName.autocapitalizationType = UITextAutocapitalizationType.words

-1
extension String {
    var lowercased:String {
        var result = Array<Character>(self.characters);
        if let first = result.first { result[0] = Character(String(first).uppercaseString) }
        return String(result)
    }
}

-1

W przypadku swift 5 możesz po prostu zrobić tak:

yourString.firstUppercased

Przykład: „abc” -> „Abc”


Nie ma pierwszej nieruchomości w Swift
Leo Dabus
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.