String Length in Swift: Not Just count, But a Whole Adventure

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why is "String Length" Not Just a Number?

\n\n

Imagine you are writing an iOS app. A user enters their name into a text field. Simple, right? But what if the name contains emoji, diacritical marks (e.g., "café"), or hieroglyphs? Suddenly, the simple task of "getting the string length" turns into a detective story with elements of Unicode.

\n\n

In Swift, working with strings is not just about counting characters. It's a journey into the world of grapheme clusters, Unicode scalars, and the legacy of Objective-C (yes, NSString is still with us). If you are just starting to learn Swift or are switching from other languages, this article is for you. We will break down how to correctly determine the length of a string, what pitfalls await you, and when to use count versus NSString.

\n\n

This material is based on a real popular question from Stack Overflow. Thousands of developers have stumbled on this topic. Let's not repeat their mistakes. Let's go!

\n\n
\n\n

1. The Basics: The count Property of String

\n\n

The most obvious way to get the length of a string in Swift is to use the count property. It returns the number of "characters" (Character) in the string. But what is a character for Swift?

\n\n
let greeting = "Привет, мир!"\nprint(greeting.count) // 12 (including the space and exclamation mark)
\n\n

It works as expected. But let's make it more complicated:

\n\n
let emojiString = "👨‍👩‍👧‍👦"\nprint(emojiString.count) // 1 (!!!)
\n\n

One? Seriously? But visually, this is a whole family of four people. What's the catch?

\n\n

The answer lies in how Swift handles strings. count does not count bytes or individual Unicode characters, but extended grapheme clusters. This is a sequence of one or more Unicode scalars that are perceived by the user as a single character. The "family" emoji consists of several parts, but Swift counts them as one character because that's how a human sees them.

\n\n

This behavior is not a bug, but a feature. Swift is designed with internationalization in mind. If count counted every Unicode scalar, the string "café" (with the single character é) could give a different result depending on how é is encoded: as a single character U+00E9 or as a combination of e + accent (U+0065 + U+0301).

\n\n
let cafe1 = "café" // é as a single character\nlet cafe2 = "cafe\\u{0301}" // e + accent\nprint(cafe1.count) // 4\nprint(cafe2.count) // 4 (although the string has 5 scalars)
\n\n

Swift counts both variants as 4 characters because the user sees "café" as 4 letters. This is the magic of grapheme clusters.

\n\n
\n\n

2. An Alternative Approach: NSString and the length Property

\n\n

Sometimes you need to get not the "human" number of characters, but the number of UTF-16 code units. For example, when working with legacy APIs, Core Text, or when transferring data in formats that expect length in UTF-16 (like some network protocols).

\n\n

This is where NSString comes to the rescue — the good old class from Objective-C. Swift strings are automatically bridged to NSString, so you can use its length property:

\n\n
let swiftString = "👨‍👩‍👧‍👦"\nlet nsString = swiftString as NSString\nprint(nsString.length) // 11 (number of UTF-16 units)
\n\n

Why 11? Because the composite "family" emoji takes up 11 units in UTF-16 (each component is encoded as a surrogate pair or a separate character). If you are working with text that will be processed by old C libraries or APIs expecting NSString, use length. But remember: this is not the number of characters the user sees.

\n\n

Another nuance: NSString does not account for grapheme clusters. For the string "café" (the second variant), length will return 5, although count returns 4. Conclusion: choose the met

Blogs

Book Recommendations