This is part of the FormatStyle Deep Dive series

The ByteCountFormatStyle allows you to output a byte count to a more easily readable format (KB, MB, GB, etc.).

Download the Xcode Playground with all examples

See the examples as a gist

let terabyte: Int64 = 1_000_000_000_000

terabyte.formatted(.byteCount(style: .binary))  // "931.32 GB"
terabyte.formatted(.byteCount(style: .decimal)) // "1 TB"
terabyte.formatted(.byteCount(style: .file))    // "1 TB"
terabyte.formatted(.byteCount(style: .memory))  // "931.32 GB"

.binary and .memory use base 16 counts, while .decimal and .file use base 10.

You can also specify the display unit with the allowedUnits parameter:

terabyte.formatted(.byteCount(style: .file, allowedUnits: .bytes)) // "1,000,000,000,000 bytes"
terabyte.formatted(.byteCount(style: .file, allowedUnits: .kb))    // "1,000,000,000 kB"
terabyte.formatted(.byteCount(style: .file, allowedUnits: .mb))    // "1,000,000 MB"

You can specify if the formatter will convert a 0 value into a spelled out string:

Int64(0).formatted(.byteCount(style: .file, allowedUnits: .mb, spellsOutZero: true))   // "Zero bytes"
Int64(0).formatted(.byteCount(style: .file, allowedUnits: .mb, spellsOutZero: false))  // "0 MB"

You can also specify if you’d like for the raw byte count to be included in the string:

terabyte.formatted(.byteCount(style: .file, allowedUnits: .mb, includesActualByteCount: true))  // "1,000,000 MB (1,000,000,000,000 bytes)"
terabyte.formatted(.byteCount(style: .file, allowedUnits: .mb, includesActualByteCount: false)) // "1,000,000 MB"

Mix and match as you please.

terabyte.formatted(.byteCount(style: .file, allowedUnits: .all, spellsOutZero: true, includesActualByteCount: true)) // "1 TB (1,000,000,000,000 bytes)"

You can set the locale by using the .locale() method:

let franceLocale = Locale(identifier: "fr_FR")

terabyte.formatted(.byteCount(style: .binary).locale(franceLocale)) // "931,32 Go"
terabyte.formatted(.byteCount(style: .decimal).locale(franceLocale)) // "1To"
terabyte.formatted(.byteCount(style: .file).locale(franceLocale)) // "1To"
terabyte.formatted(.byteCount(style: .memory).locale(franceLocale)) // "931,32 Go"


Using a new instance of the ByteCountFormatter is nearly identical to using the FormatStyle extension shown above.

let inFrench = ByteCountFormatStyle(
    style: .memory,
    allowedUnits: .all,
    spellsOutZero: false,
    includesActualByteCount: true,
    locale: Locale(identifier: "fr_FR")

inFrench.format(terabyte) // "931,32 Go (1 000 000 000 000 octets)"
terabyte.formatted(inFrench) // "931,32 Go (1 000 000 000 000 octets)"

Attributed String Output

AttributedString output can be had by this formatter by adding the .attributed parameter to the FormatStyle during use.

You can read more details in the AttributedString Output deep-dive

Download the Xcode Playground with all examples

See the examples as a gist