Q&A
How to find the length of a string in Swift
Overview
Swift's String is Unicode-correct by design. A "character" in Swift is a grapheme cluster - what a human sees as one character, even if it's composed of multiple Unicode scalars (like an emoji with a skin-tone modifier, or a letter plus a combining accent). So count gives the intuitive answer, unlike many languages where "length" means bytes or code units.
graph TD
A["string.count"] --> B[Counts Characters = grapheme clusters]
B --> C["'café' → 4, '👨👩👧' → 1"]
A --> D[Other views for other needs]
D --> D1[.utf8.count → bytes]
D --> D2[.utf16.count → UTF-16 units]
D --> D3[.unicodeScalars.count → scalars]
style A fill:#1e1b4b,color:#fff
The count Property
let greeting = "Hello"
print(greeting.count) // 5
let empty = ""
print(empty.count) // 0
print(empty.isEmpty) // true - prefer this over count == 0
Use isEmpty to check for an empty string - it's clearer and O(1), whereas computing count is O(n).
Why count Is Unicode-Correct
Because Swift counts grapheme clusters, multi-scalar characters count as one:
print("café".count) // 4 (é is one Character)
print("👍".count) // 1 (single emoji)
print("👨👩👧👦".count) // 1 (family emoji = one grapheme cluster,
// even though it's many scalars joined by ZWJ)
This matches human intuition - "how many characters do I see?" - which is usually what you want for display, validation, and limits.
Other Length Measures (String Views)
When you need a different notion of length, use the appropriate view:
let s = "café👍"
print(s.count) // 5 (Characters)
print(s.utf8.count) // 9 (UTF-8 bytes)
print(s.utf16.count) // 6 (UTF-16 code units)
print(s.unicodeScalars.count) // 5 (Unicode scalar values)
| Need | Use |
|---|---|
| User-visible character count | .count |
| Byte length (e.g. storage, network) | .utf8.count |
UTF-16 units (interop with Cocoa NSString) |
.utf16.count |
| Unicode scalar count | .unicodeScalars.count |
Performance Note: count Is O(n)
Because characters are variable-width grapheme clusters, Swift can't know the count without walking the string - so count is O(n), not O(1). Don't repeatedly call .count in a loop condition; compute it once. And for "is it empty?", use isEmpty (O(1)) rather than count == 0 (O(n)).
NSString Difference (Cocoa interop)
If you bridge to NSString (Objective-C/Cocoa), its .length returns the number of UTF-16 code units, not grapheme clusters - so an emoji may report length 2. This mismatch between Swift String.count and NSString.length is a classic source of bugs when mixing the two.
Why This Matters in Interviews
Swift interviews use this to test Unicode awareness. Key points: get length with .count, which counts Characters (grapheme clusters) - so emoji/accented characters count as one (Unicode-correct); use the string views (.utf8, .utf16, .unicodeScalars) for byte/code-unit counts; .count is O(n) (use isEmpty for emptiness); and NSString.length (UTF-16) differs from String.count. Explaining why Swift counts grapheme clusters (human-perceived characters) is the standout insight.
Common Pitfalls
- Assuming
countreturns bytes or UTF-16 units (it returns grapheme clusters). - Using
count == 0instead ofisEmpty(unnecessary O(n) work). - Repeatedly calling
.countin loops (O(n) each time - cache it). - Confusing
String.countwithNSString.length(UTF-16) during Cocoa interop, mishandling emoji. - Expecting random indexing by integer (
s[2]) - Swift strings needString.Index, notInt, because characters are variable-width.
References
- Swift Language Guide - Strings and Characters: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters/
String.count: https://developer.apple.com/documentation/swift/string