# Transforming the Case of Strings in Swift

In this blog post, I will explain the three built-in Swift options for case transformations on Strings, their locale-aware variants, and what support is offered in SwiftUI.

I will also explain why `capitalized` is equivalent to `titlecase` related functions in other programming languages and why it should not be mixed up with "Title Case" in natural languages.

This blog post is NOT about the various case styles (`camelCase`, `PascalCase`, `snake_case` or `kebab-case`) for naming variables.

Let's get started.

A natural language has a variety of case styles. Here are common case styles in the English language.

| Case style | Example |
| --- | --- |
| Sentence case | The quick brown fox jumps over the lazy dog |
| All uppercase / All caps | THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG |
| All lowercase | the quick brown fox jumps over the lazy dog |
| Start case | The Quick Brown Fox Jumps Over The Lazy Dog |
| Title Case | The Quick Brown Fox Jumps over the Lazy Dog |

Programming languages may have built-in support for some but not all of these cases. In Swift we have:

| Swift API | Case style |
| --- | --- |
| [uppercased()](https://developer.apple.com/documentation/swift/stringprotocol/uppercased()) | All uppercase / All caps |
| [lowercased()](https://developer.apple.com/documentation/swift/stringprotocol/lowercased()) | All lowercase |
| [capitalized](https://developer.apple.com/documentation/swift/stringprotocol/capitalized) | Start case |

```swift
let example = "The Quick Brown Fox Jumps over the Lazy Dog"
example.lowercased() // the quick brown fox jumps over the lazy dog
example.uppercased() // THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG
example.capitalized // The Quick Brown Fox Jumps Over The Lazy Dog
```

Let's ignore the confusing fact that `lowercased()` and `uppercased()` are functions and `capitalized` is a property.

What I do want to address is the confusion that other programming languages may use different names for Swift's [capitalized](https://developer.apple.com/documentation/foundation/nsstring/1416784-capitalized). Kotlin has [titlecase](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/titlecase.html). VBA has something called "proper case".

> In text processing, title case usually involves the capitalization of all words irrespective of their part of speech.

What programmers call "title case" (or in Swift: `capitalized`) is known as Start Case by authors which is a simplified variant.

As software programmers, we mean the mapping that is applied to the initial character in a word according to the mapping rules defined in the [Unicode Standard](https://www.unicode.org/versions/Unicode15.0.0/ch05.pdf#G21180).

> The titlecase mapping in Unicode differs from the [uppercase](https://www.unicode.org/glossary/#uppercase) mapping in that a number of characters require special handling. These are chiefly [ligatures](https://www.unicode.org/glossary/#ligature) and [digraphs](https://www.unicode.org/glossary/#digraph) such as 'fl', 'dz', and 'lj', plus a number of [polytonic](https://www.unicode.org/glossary/#polytonic) Greek characters. For example, U+01C7 (LJ) maps to U+01C8 (Lj) rather than to U+01C9 (lj).

By the way, the topic of case mapping is so complicated and important that it has its own [FAQ](https://unicode.org/faq/casemap_charprop.html).

Some case mappings depend on language or locale. Therefore Swift provides variants for case transformation considering the locale.

```swift
"i".uppercased(with: Locale(identifier: "tr_TR")) // returns "İ"
"ı".uppercased(with: Locale(identifier: "tr_TR")) // returns "I"
```

For convenience reasons Swift also provides APIs to get the case transformation in the current locale

* [`localizedUppercase`](https://developer.apple.com/documentation/swift/stringprotocol/localizeduppercase)
    
* [`localizedLowercase`](https://developer.apple.com/documentation/swift/stringprotocol/localizedlowercase)
    
* [`localizedCapitalized`](https://developer.apple.com/documentation/swift/stringprotocol/localizedcapitalized)
    

> When working with text that’s presented to the user, use locale-aware APIs

Another important fact to know is that <mark>case transformations aren’t guaranteed to be symmetrical or to produce strings of the same lengths as the originals.</mark>

```swift
"Straße".count // 6
"Straße".uppercased().count // 7

"Straße".uppercased() // STRASSE
```

Let's talk about SwiftUI.

You have support for lowercase and uppercase transformation with [textCase(\_:)](https://developer.apple.com/documentation/swiftui/text/case) introduced with iOS 14. But no capitalized option.

```swift
struct ContentView: View {
    var example = "heLLo woRLd"
    var body: some View {
        VStack {
            Text(example) // heLLo woRLd
            Text(example).textCase(.lowercase) // hello world
            Text(example).textCase(.uppercase) // HELLO WORLD
        }
        .padding()
    }
}
```

You can build a custom Swift property wrapper as [explained by John Sundell](https://www.swiftbysundell.com/articles/property-wrappers-in-swift/).

```swift
@propertyWrapper struct Capitalized {
    var wrappedValue: String {
        didSet { wrappedValue = wrappedValue.capitalized }
    }
    
    init(wrappedValue: String) {
        self.wrappedValue = wrappedValue.capitalized
    }
}
```

Then use it in your SwiftUI view.

```swift
struct ContentView: View {
    @Capitalized
    var example = "heLLo woRLd"
    
    var body: some View {
        VStack {
            Text(example) // Hello World
        }
        .padding()
    }
}
```

You can also build a more complicated Swift property wrapper that accepts the case for transformation as [shown by Andy Ibanez](https://www.andyibanez.com/posts/understanding-property-wrappers-swift/).
