What it is
Realm is an embedded object database for Swift with live, auto-updating objects, reactive queries and optional device-to-cloud sync.
Subclass Object with @Persisted properties. Queries return live, lazily-loaded results that update automatically and can be observed.
Installation
.package(url: "https://github.com/realm/realm-swift.git", from: "20.0.0")Getting started
The smallest useful thing you can do with it, and what each part means.
swift
final class Book: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var id: ObjectId
@Persisted(indexed: true) var title: String
@Persisted var year: Int
@Persisted var author: Author?
}
let realm = try await Realm()
try await realm.asyncWrite {
realm.add(Book(value: ["title": "Dune", "year": 1965]))
}
// Live and lazy — not loaded into memory until accessed.
let recent = realm.objects(Book.self)
.where { $0.year >= 1990 }
.sorted(by: \.year, ascending: false)
let token = recent.observe { changes in
switch changes {
case .initial(let books): render(books)
case .update(_, let deletions, let insertions, let modifications):
applyDiff(deletions, insertions, modifications)
case .error(let error): report(error)
}
}Advanced usage
Where the library earns its place over a simpler alternative.
swift
// Realm objects are confined to the thread that created them.
// Passing one across threads throws — use a ThreadSafeReference.
let reference = ThreadSafeReference(to: book)
DispatchQueue.global().async {
let realm = try! Realm()
guard let book = realm.resolve(reference) else { return }
try! realm.write { book.year = 1966 }
}
let config = Realm.Configuration(
schemaVersion: 2,
migrationBlock: { migration, oldVersion in
if oldVersion < 2 {
migration.enumerateObjects(ofType: Book.className()) { old, new in
new?["isbn"] = old?["legacyIsbn"] ?? ""
}
}
}
)
Realm.Configuration.defaultConfiguration = configErrors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Realm accessed from incorrect thread
- An object or Realm instance crossed a thread boundary. Open a new Realm on that thread and resolve a ThreadSafeReference.
- Migration is required due to the following errors
- The model changed without a schema version bump. Increment schemaVersion and supply a migrationBlock.
Best practices
- Never pass Realm objects between threads; use ThreadSafeReference or re-query.
- Bump schemaVersion and write a migration for every model change.
- Invalidate observation tokens when the observer is deallocated, or they leak.
- Keep write transactions short — they block other writers.
Background
Why it exists, and what it was reacting to.
Realm stores objects directly rather than mapping them to rows, so there is no ORM layer. Its objects are live views onto the database, updating in place when the underlying data changes.
