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!

Jakiś facet
źródło

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()
    }
}
Kirsteins
źródło
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ž"
Leo Dabus
źródło
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
Masełko
źródło
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.

sam k
źródło
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())
    }
}
użytkownik2260304
źródło
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()

DURGESZ
źródło
10

Swift 2.0 (pojedyncza linia):

String(nameOfString.characters.prefix(1)).uppercaseString + String(nameOfString.characters.dropFirst())
Phil
źródło
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
oscar castellon
źródło
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.

Marc Fearby
źródło
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

Yura
źródło
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()
  }
}
Adam Sharp
źródło
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())
    }
}
użytkownik3699466
źródło
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

pierre23
źródło
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
    }
}
ericgu
źródło
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
}
Nazariy Vlizlo
źródło
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
    }
}
Matt
źródło
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()
    }
Gayratjon
źródło
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)
}
guptron
źródło
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ę.

Dan Leonard
źródło
0

Aktualizacja Swift 3

replaceRangeFunc jest terazreplaceSubrange

nameOfString.replaceSubrange(nameOfString.startIndex...nameOfString.startIndex, with: String(nameOfString[nameOfString.startIndex]).capitalized)
Brendt Bly
źródło
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.

Patrick Beard
źródło
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: " ")
    }
}
Daniel R.
źródło
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"
Shilpriya
źródło
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()
    }
}
Ashu
źródło
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
Pranit
źródło
-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)
    }
}
jan07
źródło
-1

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

yourString.firstUppercased

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

Hula
źródło
Nie ma pierwszej nieruchomości w Swift
Leo Dabus