An RFC 9562 compliant UUIDV7 data type with cross-platform support and support for popular libraries.
import UUIDV7
import Foundation
let id = UUIDV7()
let id2 = UUID()
// 0198143f-f09c-772d-a29a-42b1ca62e784
print(id.uuidString)
// d486cf16-e095-4ad0-a871-492623cd654c
print(id2.uuidString)Swift’s UUID type in Foundation represents any kind of UUID, but most commonly it is used as a version 4 UUID. Version 4 UUIDs are generated entirely based on random data which is fine, but runs into an ordinality problem as a result of the data being entirely random. For instance, how do you sort a collection by a UUID? Is that even a reasonable thing to do?
UUIDV7 on the other hand, embeds a timestamp in its most significant 48 bits which enables ordinality across ids. Therefore, you can sort a collection by referring to a UUIDV7 as a sort key.
One of the most common use cases for such a need is as a primary key in databases. UUIDs make great primary keys because of their randomness, but the complete randomness of v4 UUIDs are poor for index locality. Since UUIDV7 uses a timestamp alongside random data, it has better index locality whilst still maintaining similar levels of randomness to v4 UUIDs.
UUIDV7 holds a few extra properties that cannot be guaranteed in a typical Foundation UUID, most notably the timestamp and the notion of ordinality.
On the timestamp, one could easily make an extension property on a Foundation UUID that interprets the first 48-bits as a timestamp, but this comes as the expense of the caller needing to be aware that such a property only holds true for UUID versions that use a timestamp in the first place. Given that most Foundation UUID instances are v4 UUIDs, this could easily be misused.
On ordinality, Foundation’s UUID conforms to Comparable, but such a conformance falls into the same pitfalls as the timestamp case due to the lack of ordinality in typical v4 UUIDs. Additionally, Foundation UUID’s Comparable conformance is limited to specific platform versions (iOS 17+, macOS 14+, watchOS 10+, tvOS 17+).
UUIDV7 conforms to RawRepresentable and uses a Foundation UUID as its raw value. Additionally, it also implements dynamic member lookup on Foundation UUID’s properties, so you can access all the typical properties (and any that are added in the future) just as you would on a typical UUID.
RFC 9562 does not require subsequent UUIDV7 generations to have a notion of being monotonically increasing. In other words, this property is not a strict requirement.
import UUIDV7
let id1 = UUIDV7()
let id2 = UUIDV7()
assert(id2 > id1) // Not required to be true by RFC 9562.However, the RFC also outlines that one may replace the 12 random bits from the rand_a field with data that holds, and the implementation is this library uses those bits to uphold the property of monotonically increasing generations. This is even the case when the user changes their system clock backwards far into the past. In other words, this property is guaranteed 100% of the time by the library.
import UUIDV7
let id1 = UUIDV7()
let id2 = UUIDV7()
assert(id2 > id1) // True 100% of the time in this library.If you do not want to maintain the property of monotonically increasing generations, you can pass the current date in the initializer instead.
import UUIDV7
let id1 = UUIDV7(.now)
let id2 = UUIDV7(.now)
assert(id2 > id1) // No longer true 100% of the time.The library ships with UUID v7 support to popular libraries in the ecosystem, each behind a package trait. Package traits will only compile the dependency for their specific library when you enable them. You can learn more about package traits here or the philosohpy for how they were used in this library here.
- Tagged
- Trait:
SwiftUUIDV7Tagged - Adds convenience initializers to
Taggedthat supportUUIDV7generations.
- Trait:
- GRDB
- Trait:
SwiftUUIDV7GRDB - Adds
DatabaseValueConvertibleandStatementColumnConvertibleconformances toUUIDV7. - Adds
DatabaseFunctioninstances for generating, parsing, and extracting properties fromUUIDV7.
- Trait:
- StructuredQueries
- Trait:
SwiftUUIDV7StructuredQueries - Adds a
QueryBindableconformance toUUIDV7. - Adds
UUIDV7.BytesRepresentationandUUIDV7.UppercaseRepresentationcolumn representations ofUUIDV7.
- Trait:
- Dependencies
- Trait:
SwiftUUIDV7Dependencies - Adds a
UUIDV7Generatordependency. - Adds an initializer to
UUIDGeneratorthat generatesUUIDV7instances under the hood.
- Trait:
- SQLiteData
- Trait:
SwiftUUIDV7SQLiteData - Conforms UUIDV7 to
IdentifierStringConvertibleto make it compatible with CloudKit sync. - This trait also enables
SwiftUUIDV7GRDBandSwiftUUIDV7StructuredQueries.
- Trait:
Additionally, UUIDV7 conforms to EntityIdentifierConvertible from AppIntents, which is available without a need to specify a trait when building for Apple platforms.
You can add Swift UUIDV7 to an Xcode project by adding it to your project as a package.
⚠️ At of the time of writing this, Xcode 26 (Beta 5) does not seem to include a UI for enabling traits on swift packages through theFiles > Add Package Dependenciesmenu. If you want to enable traits, you will have to install the library inside a local swift package that lives outside your Xcode project.
If you want to use Swift UUIDV7 in a SwiftPM project, it’s as simple as adding it to your Package.swift:
dependencies: [
.package(
url: "https://github.com/mhayes853/swift-uuidv7",
from: "0.1.0",
// You can omit the traits if you don't need any of them.
traits: ["SwiftUUIDV7GRDB"]
),
]This library is licensed under an MIT License. See LICENSE for details.