As an iOS developer, I often find myself in situations where I want to quickly prototype the implementation of an abstract data layer. Evolving from a simple, probably inefficient and temporary in-memory solution, to a more robust and efficient disk-based solution, that is persisted across app launches.

However committing right away to a suitable configuration for the Realm database is at times a bit overwhelming. A possibility to defer the configuration to a later stage, and transition easily to it later, would be a great help.

And then there are those times when a custom configuration is just redundant for small apps, and a simple, default configuration would suffice. In such scenarios the default Realm comes to the rescue.

What is Default Realm?

It is a realm that is created automatically by the RealmSwift framework when the module is imported in any Swift file.

import RealmSwift

// The default Realm is created automatically

It is a disk-based Realm, which is persisted to disk and saves the data across app launches. An explicit configuration is not required to create the default Realm and the initializer does not require any arguments.

Usage

To use the default Realm, you need to import the RealmSwift module in your Swift file and initialize the Realm instance, without any arguments.

import RealmSwift

do {
    let defaultRealm: Realm = try Realm()
    // Use the default Realm here
    print("Opened default Realm: \(defaultRealm)")
} catch {
    // Handle error opening the default Realm
    print("Error opening default Realm: \(error)")
}

Successfully opening the default Realm will print the Realm instance to the console.

Opened default Realm: Realm(rlmRealm: <RLMRealm: 0x6000035180b0>)

Default Configuration

It is initialized with the default configuration, which includes the following settings:

  1. File URL:

    On iOS, the default Realm is created in the Documents directory of the app’s sandbox. On macOS, the default Realm is created in the Application Support directory of the app’s sandbox.

    In both cases, the Realm file is named default.realm.

    Realm’s auxiliary files are stored in the same directory. The directory tree looks like this:

    Documents/
    ├── default.realm
    ├── default.realm.lock
    ├── default.realm.management
    │   ├── access_control.control.mx
    │   ├── access_control.new_commit.cv
    │   ├── access_control.pick_writer.cv
    │   ├── access_control.versions.mx
    │   └── access_control.write.mx
    └── default.realm.note
    
  2. In-Memory Identifier:

    Since it is a disk-based Realm, the inMemoryIdentifier property is not set.

  3. Sync Configuration:

    It is not configured for sync, so the syncConfiguration property is not set.

  4. Encryption Key:

    It does not have encryption enabled, so the encryptionKey property is not set.

  5. Read-Only:

    Read and write operations are allowed. The readOnly property is set to false.

  6. Schema Version:

    The schema version is 0.

  7. Migration Block:

    It does not have a migration block set.

  8. Delete Realm If Migration Needed:

    The deleteRealmIfMigrationNeeded property is set to false, implying that the Realm is not deleted if a migration is needed.
    Beware that an exception is thrown if a migration is needed.

  9. Should Compact On Launch:

    The shouldCompactOnLaunch property is set to nil, implying that the Realm is not compacted on launch.

  10. Object Types:

    It does not have any object types defined.

  11. Seed File Path:

    The seed property is not set, implying that the Realm is not seeded with data.

Custom Configuration

Although an explicit configuration is not required to create the default Realm, in times when you want to use the default Realm as the primary storage for your app, you can create a custom configuration.

The following are some scenarios where you might want to create a custom configuration for the default Realm:

  1. Custom File URL:

    You want to store the Realm file in a custom location.

  2. Custom Schema Version:

    You want to set a schema version for the Realm in order to perform migrations.

  3. Custom Migration Block:

    You want to define a migration block to handle schema migrations.

  4. Custom Object Types:

    You want to define custom object types for the Realm.

  5. Custom Encryption Key:

    You want to encrypt the Realm file.

To achieve this, you need to set the defaultConfiguration property of the Realm.Configuration struct to a custom configuration.

The following code snippet demonstrates the same:

import RealmSwift

// Define a custom URL for the default Realm
let documentsDirectoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let defaultRealmCustomURL: URL = documentsDirectoryURL.appending(path: "custom.realm")

// Define a custom configuration for the default Realm
let customConfig: Realm.Configuration = .init(
    fileURL: defaultRealmCustomURL,
    schemaVersion: 1,
    migrationBlock: { migration, oldSchemaVersion in
        if oldSchemaVersion < 1 {
            // Perform migration
        }
    }
)

// Set the default configuration to the custom configuration
Realm.Configuration.defaultConfiguration = customConfig

do {
    let defaultRealm: Realm = try Realm()
    // Use the default Realm here
    print("Opened default Realm with custom configuration: \(defaultRealm)")
} catch {
    // Handle error opening the default Realm
    print("Error opening default Realm: \(error)")
}

Successfully opening the default Realm with a custom configuration will print the Realm instance to the console.

Opened default Realm with custom configuration: Realm(rlmRealm: <RLMRealm: 0x60000350cd10>)

Use Cases

With a relatively simple and limited out-of-the-box configuration, the default Realm is suitable for the following use cases:

  1. Quick Prototyping

    When building a prototype or test app, you may want to jump quickly into development without worrying about database configuration. The default Realm is a good choice for this scenario. Once you have a working prototype, you can migrate to a custom Realm configuration if and as needed.

  2. Single-User iOS Applications

    If your iOS application is for a single user and does not require complex data relationships, the default Realm may be sufficient. This could include personal note-taking apps, to-do list apps, or a game that stores player scores and settings.

  3. Simple Data Models

    Apps that deal with simple and unconnected data models can benefit from the default Realm. This is because all your data is stored in one place, eliminating the need for managing multiple realms.

  4. Learning and Tutorials

    If you are learning how to use the Realm database or are following a tutorial, using the default Realm is a simple way to get started. You don’t have to worry about creating and managing configurations, allowing you to focus on learning the basics of Realm.

Snippets

Here are some useful snippets.

print("Default Realm file path: \((try? Realm())?.configuration.fileURL)")

Custom URL for Default Realm

let documentsDirectoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let defaultRealmCustomURL: URL = documentsDirectoryURL.appending(path: "custom.realm")

let customConfiguration: Realm.Configuration = .init(fileURL: defaultRealmCustomURL)

Realm.Configuration.defaultConfiguration = customConfiguration