Local Data Persistence Using Realm - codepath/ios_guides GitHub Wiki
Local Data Persistence - Using Realm
Overview
Realm Swift is a mobile object database that persists data on-disk and lets you read and write Swift objects without an ORM. This guide covers using Realm for local, on-device persistence in an iOS app.
Status (June 2026): MongoDB deprecated Atlas Device Sync and ended that hosted service on September 30, 2025. The local Realm database remains available as an open-source project. Active development happens on the
communitybranch ofrealm/realm-swift; the most recent release at the time of writing isv20.0.4. If you only need on-device persistence (no cloud sync), Realm still works — but for new projects you may also want to evaluate Apple's native SwiftData and Core Data before committing.
Requirements
Realm Swift's supported Xcode range moves with each release — see the install guide and the releases page for the values that match the version you're integrating. As of writing, the project ships two active release lines: a 10.54.x line that requires Xcode 16.3+, and a newer 20.x line that requires Xcode 26+. Pick the line whose Xcode requirement matches your build environment.
Other requirements (stable across recent releases):
- Deployment target of at least iOS 12.0, macOS 10.14, tvOS 12.0, watchOS 4.0, or visionOS 1.0.
- Reflection enabled — do not set
SWIFT_REFLECTION_METADATA_LEVEL = nonein your build settings, or Realm will not see your model properties.
Project Setup — Swift Package Manager (recommended)
Swift Package Manager is the simplest and most current way to add Realm to an Xcode project.
-
In Xcode, choose File ▸ Add Package Dependencies….
-
In the search box, paste the repository URL:
https://github.com/realm/realm-swift.git -
Set the Dependency Rule to Up to Next Major Version and leave the version at the latest release (see the releases page). Click Add Package.
-
When Xcode prompts you to pick a package product, select
RealmSwift(the Swift API) and click Add Package. As of10.49.3, you add eitherRealmSwiftorRealm, not both — pickRealmonly if your project is Objective-C-only. -
(Optional, but recommended for App Store submissions.) To include Realm's bundled Apple Privacy Manifest, build
RealmSwiftas a dynamic framework: in your target's General tab, expand Frameworks and Libraries, and changeRealmSwift's embed setting from Do Not Embed to Embed & Sign.
Project Setup — CocoaPods (alternative)
If your project already uses CocoaPods (see the CocoaPods guide), you can integrate Realm that way. You need CocoaPods 1.10.1 or newer.
-
From your project directory, refresh the CocoaPods spec repos:
pod repo update -
If you don't already have one, create a
Podfile:pod init -
Open the Podfile and add
RealmSwiftto your app target. The install guide currently uses a~>10pin in its example; if you're on the newer20.xline, substitute~>20instead. A minimal Podfile looks like:platform :ios, '12.0' target 'MyApp' do use_frameworks! pod 'RealmSwift', '~>10' end -
Install the dependency:
pod install -
Close the
.xcodeprojand open the generated.xcworkspaceinstead — that's the file you use from now on.
No
post_installSwift-version override is needed for modern Realm versions. The legacyconfig.build_settings['SWIFT_VERSION'] = '3.0'block that older guides recommended was a workaround for Xcode 8 and is obsolete; do not add it.
Define an Object Model
Import RealmSwift in any file that uses Realm, and subclass Object for each model. Mark stored properties with the @Persisted property wrapper (introduced in Realm Swift 10.10.0, this is the current API and replaces the older @objc dynamic / dynamic style):
import RealmSwift
class Todo: Object {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var name: String = ""
@Persisted var status: String = ""
@Persisted var ownerId: String = ""
convenience init(name: String, ownerId: String) {
self.init()
self.name = name
self.ownerId = ownerId
}
}
You can model relationships by referencing other Object types directly, including List<T> for to-many relationships.
Opening a Realm
The simplest setup uses the default on-disk realm:
let realm = try! Realm()
For more control (custom file URL, in-memory storage, schema migration) construct a Realm.Configuration and pass it to Realm(configuration:).
Saving Data
All mutations to a realm — inserts, updates, deletes — must happen inside a write transaction. The common pattern is realm.write { ... }:
let todo = Todo(name: "Do laundry", ownerId: "alice")
try! realm.write {
realm.add(todo)
}
To update an existing object, mutate its properties inside another write block:
try! realm.write {
todo.status = "InProgress"
}
To remove an object, call realm.delete(_:) inside a write block:
try! realm.write {
realm.delete(todo)
}
Retrieving Data
Read queries return live, auto-updating collections. Use realm.objects(_:) to get every instance of a type:
let todos = realm.objects(Todo.self)
Filter with the type-safe .where API (Realm Swift's modern replacement for NSPredicate string queries):
let inProgress = todos.where {
$0.status == "InProgress"
}
Because the returned Results are live, the same todos reference reflects later writes from any thread without re-querying.
Observing Changes
You can subscribe to changes on a realm, a collection, or an individual object using observe(_:). Retain the returned notification token for as long as you want updates:
let token = todos.observe { changes in
switch changes {
case .initial:
// First snapshot — Results are populated.
break
case .update(_, let deletions, let insertions, let modifications):
print("deleted: \(deletions), inserted: \(insertions), modified: \(modifications)")
case .error(let error):
fatalError("\(error)")
}
}
// When you no longer want updates:
token.invalidate()
Threading Notes
A Realm instance is tied to the thread or actor on which it was opened. To use Realm from a background thread, open a fresh Realm() on that thread, perform the write, and either pass an object's thread-safe reference (ThreadSafeReference) back to the main thread or re-fetch by primary key. For Swift concurrency / actor isolation, see Realm's actor support docs.