How to Get the Length of a String in Swift (Use count)

How to Get the Length of a String in Swift (Use count)

Written by

in

Quick answer: Use test1.count to get the number of visible characters in a Swift String. There is no length property. If you need UTF-16 code units for NSRange or UIKit APIs, use test1.utf16.count instead.

Why this happens

Swift’s String type does not have a length property. If you write test1.length, the compiler reports value of type 'String' has no member 'length'. The property you want is count.

This trips people up because many languages expose length, and Objective-C’s NSString exposes length. Swift deliberately uses count because a Swift String is a collection of extended grapheme clusters, not a fixed-size array of 16-bit code units.

The syntax has changed over Swift’s history. Early Swift used a global count() function. Swift 2 and 3 used test1.characters.count. Since Swift 4, characters was removed and you call test1.count directly. If you are following an old tutorial, that is why the code no longer compiles.

How to fix it

1. Use count for visible characters

For almost every UI or validation task, count is the correct answer. It returns the number of characters a person would see if they counted by hand.

var test1 = "Scott"
let length = test1.count
print(length) // 5

Use isEmpty when you only need to know whether the string is empty. It avoids walking the whole string just to compare the count to zero.

if test1.isEmpty {
    print("Nothing to validate")
}

2. Replace old characters.count code

If you are maintaining Swift 2 or Swift 3 code, you may still see test1.characters.count. In Swift 4 and later that produces value of type 'String' has no member 'characters'.

Change it to:

let length = test1.count

There is no need to bridge to NSString just to get a character count.

3. Pick the right count for the job

String.count counts extended grapheme clusters. That is usually what you want, but it is not the same as the number of UTF-16 code units or Unicode scalars.

let family = "πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦"

print(family.count)           // 1 visible character
print(family.utf16.count)     // 11 UTF-16 code units
print(family.unicodeScalars.count) // 7 Unicode scalars

Use utf16.count when you are working with NSRange, UITextField offsets, or other APIs that measure strings in UTF-16 code units. For example, a range that comes back from NSString or NSAttributedString is expressed in UTF-16 units, not in Swift characters.

let text = "Hello πŸ‘‹"
let nsRange = NSRange(location: 0, length: text.utf16.count)

If an older Objective-C API requires an NSString, bridging and asking for length gives the same UTF-16 count:

let nsLength = (text as NSString).length

Do not use that as a general replacement for count. It gives a different answer for emoji, flags, and characters built from combining marks.

4. Cache the count in tight loops

count is not a stored property. Swift has to walk the string to find grapheme cluster boundaries, so the cost grows with the length of the string. If you need the same count repeatedly, store it once.

let length = text.count
for index in 0..<length {
    // use length instead of calling text.count each time
}

For very large strings in performance-sensitive code, measure before optimizing. Do not replace count with utf16.count just because it looks faster; it changes the meaning of your code.

How to prevent it

  • Use count, not length, on Swift String values.
  • Use isEmpty instead of count == 0 for empty checks.
  • Do not assume count equals utf16.count when emoji or combining marks are possible.
  • Use String.Index for string positions; do not treat character counts as integer offsets into UTF-16 storage.
  • Test validation code with emoji, flags, and accented characters, not only ASCII text.
  • When reading older Swift tutorials, check whether the sample uses characters, count(), or utf16count; those are pre-Swift 4 patterns.

FAQ

Is String.count the same as NSString.length?

No. String.count counts extended grapheme clusters, while NSString.length counts UTF-16 code units. They match for plain ASCII text but can differ for emoji, flags, and characters made from multiple Unicode scalars.

Why does "πŸ‘¨β€πŸ‘©β€πŸ‘§β€πŸ‘¦".count return 1?

The family emoji is a single extended grapheme cluster made from several Unicode scalars joined together. Swift treats it as one visible character, so count returns 1 even though the underlying UTF-16 representation is longer.

Does count cost performance?

Yes, String.count may need to iterate over the string to determine grapheme cluster boundaries. For repeated use on long strings, compute it once and store the result rather than calling count inside a loop.

Sources & credits

Parts of this guide are adapted from content licensed under CC BY-SA 4.0; this article is shared under the same license.