"Missing" Zeros: Why Int Doesn't Store Leading Zeros and How to Live with It?
\n\nHave you ever tried to display the number 007 on screen and just got 7? A familiar pain? Welcome to the club of Swift developers who sooner or later face the question: "How to add leading zeros to an Int?"
This question on Stack Overflow has gathered thousands of views, and it's no surprise. It seems like a simple task — to display an order number as "001234" instead of "1234", or to show time as "09:05" instead of "9:5". But Swift, being a strictly typed language, separates the concept of "number" and "its string representation". Int is a mathematical entity. For it, 007 is simply 7. Leading zeros are lost during initialization.
In this article, we will break down all the main approaches to solving this problem. You will learn how to properly format integers, which method to choose for different tasks, and how to avoid a performance pitfall. We will go from simple string masks to the powerful NumberFormatter from Foundation. Let's go!
Why Can't Int Store "001"? A Quick Primer
\n\nBefore diving into the code, let's understand the nature of the phenomenon. Int in Swift is a 64-bit (or 32-bit on older devices) signed integer. Its internal representation is binary code. A zero on the left has no mathematical meaning.
let number = 007 // Error? No!\nprint(number) // Outputs: 7\n\nThe Swift compiler won't even let you write 007 in code (unless it's an octal literal, but that uses the 0o prefix). Conclusion: leading zeros are a formatting problem, not a data storage problem. We solve the task at the presentation level (UI, logging, export).
Method #1: The Classic — String(format:)
\n\nThe most popular answer on Stack Overflow is using the String(format:) function, inherited from Objective-C (via a bridge with NSString). It's a fast and concise way.
Example: Add 3 leading zeros
\n\nlet number = 7\nlet formatted = String(format: "%04d", number)\nprint(formatted) // "0007"\n\nThe specifier %04d means:
- \n
%— start of the specifier; \n 0— pad empty positions with zeros, not spaces; \n 4— minimum field width (4 characters); \n d— decimal integer (Int). \n
If the number is longer than 4 characters (e.g., 12345), formatting will not truncate it — you will get "12345".
\n\nPros and Cons
\n- \n
- Pros: Simple, fast, one line. Works in all Swift versions. \n
- Cons: Uses
NSStringunder the hood, which can be slightly slower than a pure Swift solution. Requires remembering C-style formatting syntax. Not localized (doesn't account for thousand separators if needed). \n
When to use: For simple cases: logs, debugging, outputting IDs, when localization is not needed.
\n\nMethod #2: Pure Swift — String(repeating:count:) + Suffix
\n\nIf you want to avoid the Objective-C bridge and write in "pure" Swift, you can do it manually. This is a great exercise for understanding strings.
\n\nextension Int {\n func leadingZeros(_ totalDigits: Int) -> String {\n let stringValue = String(self)\n let zerosCount = max(0, totalDigits - stringValue.count)\n return String(repeating: "0", count: zerosCount) + stringValue\n }\n}\n\nlet number = 42\nprint(number.leadingZeros(5)) // "00042"\n\nHow does it work?
\n- \n
- Convert the Int to a string. \n
- Calculate how many zeros need to be added:
totalDigits - length. If