Swift’s Foundation UUID type wraps a 128-bit RFC 4122 value and generates UUID v4 by default. For most iOS, macOS, and server-side Swift use cases this is fine. When you need chronologically sorted records — for CloudKit sync, SwiftData queries, or server APIs — UUID v7 provides sortable IDs without a separate timestamp column. The motivation is the same as in any other language: as documented on Wikipedia’s UUID article — Version 7, the timestamp prefix keeps B-tree indexes sequential.
Foundation UUID — the built-in option
import Foundation
// Generate a UUID v4
let id = UUID()
print(id.uuidString) // "550E8400-E29B-41D4-A716-446655440000" (uppercase)
print(id) // same — UUID conforms to CustomStringConvertible
// Parse from string
if let parsed = UUID(uuidString: "018fbe3a-4c5d-7b12-8abc-0123456789ab") {
print(parsed.version) // not built-in — see below
}
// Raw bytes (uuid is a 16-element tuple of UInt8)
let bytes = id.uuid
Foundation’s UUID does not expose a .version property. To read the version digit:
extension UUID {
var version: Int {
// Byte 6 contains version in high nibble
Int(uuid.6 >> 4)
}
}
UUID v7 in Swift
The swift-uuid-v7 package (also available as a Swift Package from github.com/nickvdyck/uuid-v7-swift) generates RFC 9562-compliant UUID v7 values and returns a Foundation UUID, making it a drop-in replacement wherever UUID() is used today.
Add the package via Swift Package Manager:
// Package.swift
dependencies: [
.package(url: "https://github.com/nickvdyck/uuid-v7-swift", from: "1.0.0")
],
targets: [
.target(name: "MyApp", dependencies: ["UUIDv7"])
]
Usage:
import UUIDv7
let id: UUID = UUIDv7() // Returns a Foundation UUID with v7 content
print(id.version) // 7 (using the extension above)
print(id.uuidString) // "018fbe3a-4c5d-7000-8abc-0123456789ab"
Because UUIDv7() returns the standard UUID type, it works anywhere UUID() works — SwiftData models, Core Data attributes, Codable structs, and API responses.
SwiftData with UUID v7
import SwiftData
import UUIDv7
@Model
final class Order {
@Attribute(.unique) var id: UUID
var totalCents: Int
var createdAt: Date
init(totalCents: Int) {
self.id = UUIDv7() // time-sortable primary key
self.totalCents = totalCents
self.createdAt = Date()
}
}
With UUID v7 as the id, a SwiftData FetchDescriptor sorted by id gives chronological order — no separate sort descriptor on createdAt needed:
let descriptor = FetchDescriptor<Order>(
sortBy: [SortDescriptor(\.id)] // chronological — v7 sorts by time
)
let orders = try context.fetch(descriptor)
Core Data with UUID v7
In the Core Data model editor, set the attribute type to UUID. In your NSManagedObject subclass:
import CoreData
import UUIDv7
extension Order {
@nonobjc class func newOrder(in context: NSManagedObjectContext) -> Order {
let order = Order(context: context)
order.id = UUIDv7() // time-sortable; sorts correctly in fetch requests
return order
}
}
A NSSortDescriptor(key: "id", ascending: true) on a Core Data fetch request will return records in insertion order because UUID v7 sorts chronologically as a string.
Codable and API responses
Foundation’s UUID encodes as a lowercase hyphenated string in JSONEncoder by default. No extra configuration is needed — UUID v7 values round-trip through Codable identically to v4:
struct UserResponse: Codable {
let id: UUID // encodes as "018fbe3a-4c5d-7b12-8abc-0123456789ab"
let email: String
}
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(UserResponse(id: UUIDv7(), email: "a@b.com"))
When to keep using UUID v4
UUID v7 embeds a 48-bit creation timestamp readable by anyone with the ID. For user-facing tokens, share links, or any UUID appearing in URLs or client-visible JSON, use UUID() (v4) instead. The CloudKit documentation recommends opaque record IDs for publicly-shared resources — another case where v4 is preferred. See UUID v4 vs UUID v7 for the full trade-off analysis.
Related reading
- UUID v4 vs v7 — visibility, sortability, and performance trade-offs
- UUID in Databases — storage in SQLite and PostgreSQL
- UUID v7 Generator — generate and inspect UUID v7 values in your browser
External references
- Apple Foundation — UUID — official Swift documentation for the built-in UUID type
- Apple SwiftData documentation — persistence framework for Swift introduced at WWDC 2023
- uuid-v7-swift on GitHub — Swift Package Manager package for RFC 9562 UUID v7 generation
- RFC 9562 — UUID specification — the IETF standard defining UUID v7
Frequently asked questions
How do I generate a UUID in Swift?
Use UUID() from the Foundation framework. It generates an RFC 4122 UUID v4 using the platform CSPRNG. The value is available as a string via uuid.uuidString (uppercase, hyphenated) or as raw bytes via the uuid tuple property. No import is needed — Foundation is available in all Apple platforms.
Does SwiftData support UUID primary keys?
Yes. Mark a property with @Attribute(.unique) and type it as UUID to use it as a stable identifier. SwiftData uses the Foundation UUID type, which produces UUID v4 by default. For UUID v7, generate the value in the model's initializer using a third-party package and assign it to the UUID-typed property.
How is UUID stored in Core Data?
Core Data has a native UUID attribute type (available since iOS 11 / macOS 10.13). It stores the value as 16 bytes internally. You can access it from Swift as a UUID? optional. Avoid storing UUIDs as String attributes — they use more space and lose type safety.