# Technical Documentation: realm/realm-swift

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/realm/realm-swift)

### Overview (`README.md`)

<picture>
    <source srcset="./media/logo-dark.svg" media="(prefers-color-scheme: dark)" alt="realm">
    <img src="./media/logo.svg" alt="realm">
</picture>

# About Realm Database

Realm is a mobile database that runs directly inside phones, tablets or wearables.
This repository holds the source code for the iOS, macOS, tvOS & watchOS versions of Realm Swift & Realm Objective-C.

## Why Use Realm

* **Intuitive to Developers:** Realm’s object-oriented data model is simple to learn, doesn’t need an ORM, and lets you write less code.
* **Built for Mobile:** Realm is fully-featured, lightweight, and efficiently uses memory, disk space, and battery life.
* **Designed for Offline Use:** Realm’s local database persists data on-disk, so apps work as well offline as they do online.

## Object-Oriented: Streamline Your Code

Realm was built for mobile developers, with simplicity in mind. The idiomatic, object-oriented data model can save you thousands of lines of code.

```swift
// Define your models like regular Swift classes
class Dog: Object {
    @Persisted var name: String
    @Persisted var age: Int
}
class Person: Object {
    @Persisted(primaryKey: true) var _id: String
    @Persisted var name: String
    @Persisted var age: Int
    // Create relationships by pointing an Object field to another Class
    @Persisted var dogs: List<Dog>
}
// Use them like regular Swift objects
let dog = Dog()
dog.name = "Rex"
dog.age = 1
print("name of dog: \(dog.name)")

// Get the default Realm
let realm = try! Realm()
// Persist your data easily with a write transaction
try! realm.write {
    realm.add(dog)
}
```
## Live Objects: Build Reactive Apps
Realm’s live objects mean data updated anywhere is automatically updated everywhere.
```swift
// Open the default realm.
let realm = try! Realm()

var token: NotificationToken?

let dog = Dog()
dog.name = "Max"

// Create a dog in the realm.
try! realm.write {
    realm.add(dog)
}

//  Set up the listener & observe object notifications.
token = dog.observe { change in
    switch change {
    case .change(let properties):
        for property in properties {
            print("Property '\(property.name)' changed to '\(property.newValue!)'");
        }
    case .error(let error):
        print("An error occurred: (error)")
    case .deleted:
        print("The object was deleted.")
    }
}

// Update the dog's name to see the effect.
try! realm.write {
    dog.name = "Wolfie"
}
```
### SwiftUI
Realm integrates directly with SwiftUI, updating your views so you don't have to.
```swift
struct ContactsView: View {
    @ObservedResults(Person.self) var persons

    var body: some View {
        List {
            ForEach(persons) { person in
                Text(person.name)
            }
            .onMove(perform: $persons.move)
            .onDelete(perform: $persons.remove)
        }.navigationBarItems(trailing:
            Button("Add") {
                $persons.append(Person())
            }
        )
    }
}
```

## Fully Encrypted
Data can be encrypted in-flight and at-rest, keeping even the most sensitive data secure.
```swift
// Generate a random encryption key
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { (pointer: UnsafeMutableRawBufferPointer) in
    guard let baseAddress = pointer.baseAddress else {
        fatalError("Failed to obtain base address")
    }
    SecRandomCopyBytes(kSecRandomDefault, 64, baseAddress)
}

// Add the encryption key to the config and open the realm
let config = Realm.Configuration(encryptionKey: key)
let realm = try Realm(configuration: config)

// Use the Realm as normal
let dogs = realm.objects(Dog.self).filter("name contains 'Fido'")
```

## Getting Started

We support installing Realm via Swift Package Manager, CocoaPods, Carthage, or by importing a dynamic XCFramework.

For more information, see our [Quick Start](docs/guides/quick-start.md).

## Documentation

The documentation can be found in the [docs/](docs/README.md) directory.

The API reference can be generated from source using
[jazzy](https://github.com/realm/jazzy/) by running `sh build.sh docs` from the root of this repository.

## Getting Help

- **Need help with your code?**: Look for previous questions with the[`realm` tag](https://stackoverflow.com/questions/tagged/realm?sort=newest) on Stack Overflow or [ask a new question](https://stackoverflow.com/questions/ask?tags=realm). For general discussion that might be considered too broad for Stack Overflow, use the [Community Forum](https://developer.mongodb.com/community/forums/tags/c/realm-sdks/58/swift/).
- **Have a bug to report?** [Open a GitHub issue](https://github.com/realm/realm-swift/issues/new). If possible, include the version of Realm, a full log, the Realm file, and a project that shows the issue.
- **Have a feature request?** [Open a GitHub issue](https://github.com/realm/realm-swift/issues/new). Tell us what the feature should do and why you want the feature.

## Building Realm

In case you don't want to use the precompiled version, you can build Realm yourself from source.

Prerequisites:

* Building Realm requires Xcode 15.3 or newer.
* Building Realm documentation requires [jazzy](https://github.com/realm/jazzy)

Once you have all the necessary prerequisites, building Realm just takes a single command: `sh build.sh build`.
You'll need an internet connection the first time you build Realm to download the core binary.
This will produce Realm.xcframework and RealmSwift.xcframework in `build/Release/`.

Run `sh build.sh help` to see all the actions you can perform (build ios/osx, generate docs, test, etc.).

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for more details!

## Code of Conduct

This project adheres to the [MongoDB Code of Conduct](https://www.mongodb.com/community-code-of-conduct).
By participating, you are expected to uphold this code. Please report
unacceptable behavior to [community-conduct@mongodb.com](mailto:community-conduct@mongodb.com).

## License

Realm Objective-C & Realm Swift are published under the Apache 2.0 license.
Realm Core is also published under the Apache 2.0 license and is available
[here](https://github.com/realm/realm-core).

## Feedback

**_If you use Realm and are happy with it, please consider sending out a tweet mentioning [@realm](https://twitter.com/realm) to share your thoughts!_**

**_And if you don't like it, please let us know what you would like improved, so we can fix it!_**

<img style="width: 0px; height: 0px;" src="https://3eaz4mshcd.execute-api.us-east-1.amazonaws.com/prod?s=https://github.com/realm/realm-swift#README.md">

---

### Overview (`docs/README.md`)

# Realm SDK for Swift
Use the Realm SDK for Swift to develop iOS, macOS, watchOS and tvOS
apps in Swift and Objective-C.

## Get Started with the Swift SDK

These docs contain minimal-explanation code examples of how to work
with the Swift SDK.

To get started with SwiftUI, see: [SwiftUI Quick Start](swiftui-tutorial.md)

### Install the Swift SDK
Use Swift Package Manager, CocoaPods, or Carthage to
Install the SDK for iOS, macOS, tvOS, and watchOS in your project.

Import `RealmSwift` in your project files to get started.

### Define an Object Schema
Use Swift to idiomatically define an object schema.

### Open a Database
The SDK's database - Realm - stores objects in files on your
device. Or you can open an in-memory database which does not
create a file.

Configure and open a database to specify the options for your database file.

### Read and Write Data
- Create, read, update, and delete objects from the device database.
- Filter data using the SDK's type-safe .where syntax, or construct an NSPredicate.

### React to Changes
Live objects mean that your data is always up-to-date.
You can register a notification handler
to watch for changes and perform some logic, such as updating
your UI. Or in SwiftUI, use the Swift property wrappers
to update Views when data changes.

## Realm SwiftUI

The Swift SDK offers property wrappers and convenience
features designed to make it easier to work with SwiftUI.
For example View code that demonstrates common SwiftUI
patterns, check out the SwiftUI documentation.

```swift
struct SearchableDogsView: View {
    @ObservedResults(Dog.self) var dogs
    @State private var searchFilter = ""

    var body: some View {
        NavigationView {
            // The list shows the dogs in the realm.
            List {
                ForEach(dogs) { dog in
                    DogRow(dog: dog)
                }
            }
            .searchable(text: $searchFilter,
                        collection: $dogs,
                        keyPath: \.name) {
                ForEach(dogs) { dogsFiltered in
                    Text(dogsFiltered.name).searchCompletion(dogsFiltered.name)
                }
            }
        }
    }
}

```

## Generating API Reference Docs

You can generate the API docs locally by running `sh build.sh docs` from the root of this repository.
This requires installation of [jazzy](https://github.com/realm/jazzy/).
You will find the output in `docs/swift_output/` and `docs/objc_output/`.

---

### Overview (`examples/README.md`)

# Realm Examples

Included in this folder are sample iOS/OSX apps using Realm.

## iOS (Objective-C)

The following examples are located in the `ios/objc/RealmExamples.xcodeproj` project:

### Simple

This app covers several introductory concepts about Realm. Without any UI distractions, just a little console output.

### TableView

This app demonstrates how Realm can be the data source for UITableViews.

You can add rows by tapping the add button and remove rows by swiping right-to-left.

The application also demonstrates how to import data in a background thread.

### GroupedTableView

A sample app to demonstrate how to use Realm to populate a table view with sections.

### Migration

This example showcases Realm's migration features.

### REST

Using data from FourSquare, this example demonstrates how to populate a Realm with external json data.

### Encryption

This simple app shows how to use an encrypted realm.

### Backlink

This simple app demonstrates how to define models with inverse relationships using `-linkingObjectsOfClass:forProperty:`.

#### Installation Instructions

1. [Download the macOS version](https://realm.io/docs/realm-mobile-platform/get-started/) of the Realm Mobile Platform.
2. Run a local instance of the Realm Mobile Platform.
3. Open the Realm Object Server Dashboard in your browser by visiting 'http://localhost:9080'.
4. Create a user account with the email 'demo@realm.io' and the password 'password'.
5. Build the Draw app and deploy it to iOS devices on the same network as your Mac.

## iOS (Swift)

In the `ios/swift/RealmExamples.xcodeproj` project, you will find the following examples:

### GettingStarted.playground

This is a Swift Playground that goes over a few Realm basics.

### Simple

This app covers several introductory concepts about Realm. Without any UI distractions, just a little console output.

### TableView

This app demonstrates how Realm can be the data source for UITableViews.

You can add rows by tapping the add button and remove rows by swiping right-to-left.

The application also demonstrates how to import data in a background thread.

### GroupedTableView

A sample app to demonstrate how to use Realm to populate a table view with sections.

### Migration

This example showcases Realm's migration features.

### Encryption

This simple app shows how to use an encrypted realm.

### Backlink

This simple app demonstrates how to define models with inverse relationships using `linkingObjectsOfClass(_:forProperty:)`.

### Projections

This app demonstrates how to define Projection on Realm Object and how to use it in SwiftUI application.

### AppClip / AppClipParent

These two targets demonstrate how to use Realm to persist data between an App Clip and its parent.

#### Example Usage

For the purpose of this example, the app clip invocation and parent application download is simulated by running each target.

For more information on complete App Clip flow see: [Responding to invocations](https://developer.apple.com/documentation/app_clips/responding_to_invocations) and [Launch Experience](https://developer.apple.com/documentation/app_clips/testing_your_app_clip_s_launch_experience).



**Note:** When testing App Group Entitlements on MacOS (including the iOS simulator), `containerURL(forSecurityApplicationGroupIdentifier:)` will always return the shared directory URL, even when the group identifier is invalid.  Be sure to test on physical devices with non-simulated iOS for expected security behavior. See [Return Value](https://developer.apple.com/documentation/foundation/filemanager/1412643-containerurl).



## OSX (Objective-C)

In the `osx/objc/RealmExamples.xcodeproj` project, you will find the following examples:

### JSONImport

This is a small OS X command-line program which demonstrates how to import data from JSON into a Realm.

Open the project in Xcode, and press "Run" to build and run the program. It will write output to the console.

## Installation Examples

The `installation/` directory contains example Xcode projects demonstrating how
to install Realm Objective-C and Realm Swift from all available methods defined
in <https://www.mongodb.com/docs/atlas/device-sdks/sdk/swift/install/#install-realm-for-ios--macos--tvos--and-watchos>.

## tvOS (Objective-C)

### DownloadCache

A tvOS app that demonstrates how to use Realm to store data and display data from a REST API.

### PreloadedData

A tvOS app that demonstrates how to use a Realm file included in your app bundle.

## tvOS (Swift)

### DownloadCache

A tvOS app that demonstrates how to use Realm to store data and display data from a REST API.

### PreloadedData

A tvOS app that demonstrates how to use a Realm file included in your app bundle.

---

### Overview (`plugin/README.md`)

# Realm Plugin

The Realm Plugin for Xcode adds several useful features for developing with Realm:

1. A LLDB script which adds support for inspecting the property values of
   persisted RLMObjects in the debugger pane.
2. File templates for RLMObject subclasses.
3. A menu item in Xcode's 'File' menu to quickly launch the Realm Browser.
   Note that this item will only appear in Xcode 7 and in unsigned versions of
   Xcode 8 or later (not recommended).

To install the Realm Plugin, open `RealmPlugin.xcodeproj` and Build. This will
prompt for your password. After building the plugin, restart Xcode.

---

### Overview (`examples/ios/swift/Migration/README.md`)

# Migration Examples

The Migration project shows several examples of migrations and migration blocks.

The purpose of this example is to provide a more in depth view of certain problems and pitfalls users might face when 
migrations get more complex and the number of versions increases.

## How to use the example

You can build and run the project as is. Migrations from all prior version to the current version will be checked:
   - v0 -> v5
   - v1 -> v5
   - v2 -> v5
   - v3 -> v5
   - v4 -> v5

The files to look at are located in the `Examples` folder. Every file contains an extract of everything necessary for
this version (schema version, objects, migration and migration checks).

If you want to compare older versions among each other (i.e. v2 -> v3) you can do so by enabling the schema version, for example:
   - Deactivate version 5 by setting `#define SCHEMA_VERSION_5 1` to `#define SCHEMA_VERSION_5 0` in `Example_v5.h`.
   - Activate version 3 by seting `#define SCHEMA_VERSION_3 0` to `#define SCHEMA_VERSION_3 1` in `Example_v3.h`.

---

### Example Projects (`docs/example-projects.md`)

# Realm SDK Example Projects
Explore engineering and expert-provided example projects to learn best
practices and common development patterns for the Swift SDK.

|Project Name|Description|Source Code|
| --- | --- | --- |
|Integrating In-App Purchases|Use [DELETE ME]'s efficient data management and synchronization capabilities to build a recipes library with in-app purchases (IAP) using StoreKit.|[Swift](https://github.com/realm/realm-swift-samples/tree/main/InAppPurchasesAtlasAppServices)|
|RTicket|Build a simple issue ticket system with Realm and SwiftUI.|[Swift](https://github.com/mongodb-developer/RTicket)|
|RCurrency|Use Realm to cache data retrieved from an API and access the data offline.|[Swift](https://github.com/realm/RCurrency)|
|RChat|Build a simple chat app with SwiftUI and Realm.|[Swift](https://github.com/realm/RChat)|

---

### Install (`docs/install.md`)

# Install the SDK for iOS, macOS, tvOS, and watchOS
## Overview
Realm SDK for Swift enables you to build iOS, macOS, tvOS,
and watchOS applications using either the Swift or Objective-C programming
languages. This page details how to install the SDK in your project and get
started.

## Prerequisites
Before getting started, ensure your development environment
meets the following prerequisites:

- Your project uses an Xcode version and minimum OS version listed in the
OS Support section of this page.
- Reflection is enabled in your project. The Swift SDK uses reflection to
determine your model's properties. Your project must not set
`SWIFT_REFLECTION_METADATA_LEVEL = none`, or the SDK cannot see properties
in your model. Reflection is enabled by default if your project does
not specifically set a level for this setting.

## Installation
You can use `SwiftPM`, `CocoaPods`, or `Carthage` to add the
Swift SDK to your project.

> Tip:
> The SDK uses Realm Core database for device data persistence. When you
install the Swift SDK, the package names reflect Realm naming.
>

#### Swiftpm

##### Add Package Dependency
In Xcode, select `File` > `Add Packages...`.

##### Specify the Repository
Copy and paste the following into the search/input box.

```sh
https://github.com/realm/realm-swift.git
```

##### Specify Options
In the options for the `realm-swift` package, we recommend setting
the `Dependency Rule` to `Up to Next Major Version`,
and enter the [current Realm Swift SDK version](https://github.com/realm/realm-swift/releases) . Then, click `Add Package`.

##### Select the Package Products
> Version changed: 10.49.3
> Instead of adding both, only add one package.
>

Select either `RealmSwift` or `Realm`, then click `Add Package`.

- If you use Swift or Swift and Objective-C APIs, add `RealmSwift`.
- If you use *only* Objective-C APIs, add `Realm`.

##### (Optional) Build RealmSwift as a Dynamic Framework
To use the Privacy Manifest supplied by the SDK, build `RealmSwift`
as a dynamic framework. If you build `RealmSwift` as a static
framework, you must supply your own Privacy Manifest.

To build `RealmSwift` as a dynamic framework:

1. In your project Targets, select your build target.
2. Go to the General tab.
3. Expand the Frameworks and Libraries element.
4. For the `RealmSwift` framework, change the
Embed option from "Do Not Embed" to "Embed & Sign."

Now, Xcode builds `RealmSwift` dynamically, and can provide the
SDK-supplied Privacy Manifest.

#### Cocoapods

If you are installing with [CocoaPods](https://guides.cocoapods.org/using/getting-started.html), you need CocoaPods 1.10.1 or later.

##### Update the CocoaPods repositories
On the command line, run `pod repo update` to ensure
CocoaPods can access the latest available Realm versions.

##### Initialize CocoaPods for Your Project
If you do not already have a Podfile for your project,
run `pod init` in the root directory of your project to
create a Podfile for your project. A Podfile allows you
to specify project dependencies to CocoaPods.

##### Add the SDK as a Dependency in Your Podfile
#### Objective-C

Add the line `pod 'Realm', '~>10'` to your main and test
targets.

Add the line `use_frameworks!` as well if it is not
already there.

When done, your Podfile should look something like this:

```text
# Uncomment the next line to define a global platform for your project
# platform :ios, '11.0'

target 'MyDeviceSDKProject' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!

# Pods for MyDeviceSDKProject
pod 'Realm', '~>10'

target 'MyRealmProjectTests' do
   inherit! :search_paths
   # Pods for testing
   pod 'Realm', '~>10'
end

end
```

#### Swift

Add the line `use_frameworks!` if it is not
already there.

Add the line `pod 'RealmSwift', '~>10'` to your main and test
targets.

When done, your Podfile should look something like this:

```text
platform :ios, '12.0'

target 'MyDeviceSDKProject' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for MyDeviceSDKProject
  pod 'RealmSwift', '~>10'

end
```

##### Install the Dependencies
From the command line, run `pod install` to fetch the
dependencies.

###### Use the CocoaPods-Generated  File

##### Use the CocoaPods-Generated .xcworkspace File
CocoaPods generates an `.xcworkspace` file for you. This
file has all of the dependencies configured. From now on,
open this file -- not the `.xcodeproj` file -- to work
on your project.

#### Carthage

If you are installing with [Carthage](https://github.com/Carthage/Carthage#installing-carthage), you need Carthage 0.33 or later.

##### Add the SDK as a Dependency in Your Cartfile
Add the SDK as a dependency by appending the line `github
"realm/realm-swift"` to your Cartfile.

You can create a Cartfile or append to an existing one by
running the following command in your project directory:

```bash
echo 'github "realm/realm-swift"' >> Cartfile
```

##### Install the Dependencies
From the command line, run `carthage update --use-xcframeworks`
to fetch the dependencies.

##### Add the Frameworks to Your Project
Carthage places the built dependencies in the `Carthage/Build`
directory.

Open your project's `xcodeproj` file in Xcode. Go to
the Project Navigator panel and click your application
name to open the project settings editor. Select the
General tab.

In Finder, open the `Carthage/Build/` directory. Drag the
`RealmSwift.xcframework` and `Realm.xcframework` files
found in that directory to the Frameworks,
Libraries, and Embedded Content section of your
project's General settings.

#### Dynamic Framework

##### Download and Extract the Framework
Download the [latest release of the Swift SDK](https://github.com/realm/realm-swift/releases) and extract the zip.

##### Copy Framework(s) Into Your Project
Drag `Realm.xcframework` and `RealmSwift.xcframework` (if using)
to the File Navigator of your Xcode project. Select the
Copy items if needed checkbox and press Finish.

> Tip:
> If using the Objective-C API within a Swift project, we
recommend you include both Realm Swift and Realm Objective-C in your
project. Within your Swift files, you can access the Swift API and
all required wrappers. Using the RealmSwift API in mixed
Swift/Objective-C projects is possible because the vast majority of
RealmSwift types are directly aliased from their Objective-C
counterparts.
>

## Import the SDK
> Tip:
> The SDK uses Realm Core database for device data persistence. When you
import the Swift SDK, the package names reflect Realm naming.
>

Add the following line at the top of your source files to use the SDK:

#### Objective-C

```objectivec
#include <Realm/Realm.h>

```

#### Swift

```swift
import RealmSwift

```

## App Download File Size
The SDK should only add around 5 to 8 MB to your app's download
size. The releases we distribute are significantly larger because they
include support for the iOS, watchOS and tvOS simulators, some debug symbols,
and bitcode, all of which are stripped by the App Store automatically when
apps are downloaded.

## Troubleshooting
If you have build issues after using one of these methods to install
the SDK, see our troubleshooting guidelines
for information about resolving those issues.

## OS Support
> Important:
> There are special considerations when using the SDK with
tvOS. See Build for tvOS for more information.
>

### Xcode 15
> Version changed: 10.50.0
> Minimum required Xcode version is 15.1
>

|Supported OS|Realm|
| --- | --- |
|iOS 12.0+|X|
|macOS 10.14+|X|
|tvOS 12.0+|X|
|watchOS 4.0+|X|
|visionOS 1.0+|X|

### Xcode 14
> Version changed: 10.50.0
> Removed support for Xcode 14.
>

Swift SDK version 10.50.0 drops support for Xcode 14. For v10.49.3 and earlier,
these Xcode 14 requirements apply:

- [Xcode](https://developer.apple.com/xcode/) version 14.1 or higher.
- When using Xcode 14, a target of iOS 11.0 or higher, macOS 10.13 or higher, tvOS 11.0 or higher, or watchOS 4.0 or higher.

## Swift Concurrency Support
The Swift SDK supports Swift's concurrency-related language features.
For best practices on using the Swift SDK's concurrency features, refer
to the documentation below.

### Async/Await Support
Starting with Realm Swift SDK Versions 10.15.0 and 10.16.0, many of the
Realm APIs support the Swift async/await syntax. Projects must
meet these requirements:

|Swift SDK Version|Swift Version Requirement|Supported OS|
| --- | --- | --- |
|10.25.0|Swift 5.6|iOS 13.x|
|10.15.0 or 10.16.0|Swift 5.5|iOS 15.x|

If your app accesses Realm in an `async/await` context, mark the code
with `@MainActor` to avoid threading-related crashes.

For more information about async/await support in the Swift SDK, refer
to Swift Concurrency: Async/Await APIs.

### Actor Support
The Swift SDK supports actor-isolated realm instances. For more information,
refer to Use Realm with Actors - Swift SDK.

## Apple Privacy Manifest
> Version changed: 10.49.3
> Build RealmSwift as a dynamic framework to include the Privacy Manifest.
>

Apple requires apps that use `RealmSwift` to provide a privacy manifest
containing details about the SDK's data collection and use practices. The
bundled manifest file must be included when submitting new apps or app updates
to the App Store. For more details about Apple's requirements, refer to
[Upcoming third-party SDK requirements](https://developer.apple.com/support/third-party-SDK-requirements/)
on the Apple Developer website.

Starting in Swift SDK version 10.46.0, the SDK ships with privacy manifests
for `Realm` and `RealmSwift`. Each package contains its own privacy manifest
with Apple's required API disclosures and the reasons for using those APIs.

You can view the privacy manifests in each package, or in the `realm-swift`
GitHub repository:

- `Realm`: [https://github.com/realm/realm-swift/blob/master/Realm/PrivacyInfo.xcprivacy](https://github.com/realm/realm-swift/blob/master/Realm/PrivacyInfo.xcprivacy)
- `RealmSwift`: [https://github.com/realm/realm-swift/blob/master/RealmSwift/PrivacyInfo.xcprivacy](https://github.com/realm/realm-swift/blob/master/RealmSwift/PrivacyInfo.xcprivacy)

To include these manifests in a build target that uses `RealmSwift`, you must
build `RealmSwift` as a dynamic framework. For details, refer to the Swift
Package Manager Installation instructions step
**(Optional) Build RealmSwift as a Dynamic Framework**.

The Swift SDK does not include analytics code in builds for the App Store.

You may need to add additional disclosures to your app's privacy manifest
detailing your data collection and use practices when using these APIs.

For more information, refer to Apple's
[Privacy manifest files documentation](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files).

---

### Guides Logging (`docs/guides/logging.md`)

# Logging - Swift SDK
You can set or change your app's log level when developing or debugging
your application. You might want to change the log level to log different
amounts of data depending on your development needs.

## Set or Change the Realm Log Level
You can set the level of detail reported by the Realm Swift SDK. Set the
log level for the default logger with `Logger.shared.level`:

```swift
Logger.shared.level = .trace

```

The `RLMLogLevel` enum represents the different levels of logging you can configure.

You can change the log level to increase or decrease verbosity at different
points in your code.
```swift
// Set a log level that isn't too verbose
Logger.shared.level = .warn

// Later, when trying to debug something, change the log level for more verbosity
Logger.shared.level = .trace

```

## Turn Off Logging
The default log threshold level for the Realm Swift SDK is `.info`. This
displays some information in the console. You can disable logging entirely
by setting the log level to `.off`:

```swift
Logger.shared.level = .off

```

## Customize the Logging Function
Initialize an instance of a `Logger` and define the function to use for logging.

```swift
// Create an instance of `Logger` and define the log function to invoke.
let logger = Logger(level: .detail) { level, message in
    // You may pass log information to a logging service, or
    // you could simply print the logs for debugging. Define
    // the log function that makes sense for your application.
    print("REALM DEBUG: \(Date.now) \(level) \(message) \n")
}

```

> Tip:
> To diagnose and troubleshoot errors while developing your application, set the
log level to `debug` or `trace`. For production deployments, decrease the
log level for improved performance.
>

You can set a logger as the default logger for your app with `Logger.shared`.
After you set the default logger, you can change the log level during the app
lifecycle as needed.

```swift
let logger = Logger(level: .info) { level, message in
    // You may pass log information to a logging service, or
    // you could simply print the logs for debugging. Define
    // the log function that makes sense for your application.
    print("REALM DEBUG: \(Date.now) \(level) \(message) \n")
}

// Set a logger as the default
Logger.shared = logger

// After setting a default logger, you can change
// the log level at any point during the app lifecycle
Logger.shared.level = .debug

```

---

### Guides Quick Start (`docs/guides/quick-start.md`)

# Quick Start - Swift SDK
This Quick Start demonstrates how to use Realm with the Realm Swift SDK.
Before you begin, ensure you have installed the Swift SDK.

> Seealso:
> If your app uses SwiftUI, check out the [SwiftUI Quick Start](swiftui-tutorial.md).
>

## Import Realm
Near the top of any Swift file that uses Realm, add the following import
statement:

```swift
import RealmSwift

```

## Define Your Object Model
For a local realm, you can define your object model directly in code.

```swift
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
   }
}

```

## Open a Realm
In a local realm, the simplest option to open a realm
is to use the default realm with no configuration parameter:

```swift
// Open the default realm
let realm = try! Realm()

```

You can also specify a `Realm.Configuration`
parameter to open a realm at a specific file URL, in-memory, or with a
subset of classes.

For more information, see: Configure and Open a Realm.

## Create, Read, Update, and Delete Objects
Once you have opened a realm, you can modify it and its objects
in a write transaction block.

To create a new Todo object, instantiate the Todo class and add it to the realm in a write block:

```swift
let todo = Todo(name: "Do laundry", ownerId: user.id)
try! realm.write {
    realm.add(todo)
}

```

You can retrieve a live collection of all todos in the realm:

```swift
// Get all todos in the realm
let todos = realm.objects(Todo.self)

```

You can also filter that collection using where:

```swift
let todosInProgress = todos.where {
    $0.status == "InProgress"
}
print("A list of all todos in progress: \(todosInProgress)")

```

To modify a todo, update its properties in a write transaction block:

```swift
// All modifications to a realm must happen in a write block.
let todoToUpdate = todos[0]
try! realm.write {
    todoToUpdate.status = "InProgress"
}

```

Finally, you can delete a todo:

```swift
// All modifications to a realm must happen in a write block.
let todoToDelete = todos[0]
try! realm.write {
    // Delete the Todo.
    realm.delete(todoToDelete)
}

```

## Watch for Changes
You can watch a realm, collection, or object for changes with the `observe` method.

```swift
// Retain notificationToken as long as you want to observe
let notificationToken = todos.observe { (changes) in
    switch changes {
    case .initial: break
        // Results are now populated and can be accessed without blocking the UI
    case .update(_, let deletions, let insertions, let modifications):
        // Query results have changed.
        print("Deleted indices: ", deletions)
        print("Inserted indices: ", insertions)
        print("Modified modifications: ", modifications)
    case .error(let error):
        // An error occurred while opening the Realm file on the background worker thread
        fatalError("\(error)")
    }
}

```

Be sure to retain the notification token returned by `observe` as
long as you want to continue observing. When you are done observing,
invalidate the token to free the resources:

```swift
// Invalidate notification tokens when done observing
notificationToken.invalidate()

```

---

### Guides Swift Concurrency (`docs/guides/swift-concurrency.md`)

# Swift Concurrency - Swift SDK
Swift's concurrency system provides built-in support for writing asynchronous
and parallel code in a structured way. For a detailed overview of the
Swift concurrency system, refer to the [Swift Programming Language Concurrency
topic](https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html).

While the considerations on this page broadly apply to using realm with
Swift concurrency features, Realm Swift SDK version 10.39.0 adds support
for using Realm with Swift Actors. You can use Realm isolated to a single
actor or use Realm across actors.

Realm's actor support simplifies using Realm in a MainActor and background actor
context, and supersedes much of the advice on this page regarding concurrency
considerations. For more information, refer to Use Realm with Actors - Swift SDK.

## Realm Concurrency Caveats
As you implement concurrency features in your app, consider this caveat
about Realm's threading model and Swift concurrency threading behaviors.

### Suspending Execution with Await
Anywhere you use the Swift keyword `await` marks a possible suspension
point in the execution of your code. With Swift 5.7, once your code suspends,
subsequent code might not execute on the same thread. This means that
anywhere you use `await` in your code, the subsequent code could be
executed on a different thread than the code that precedes or follows it.

This is inherently incompatible with Realm's live object paradigm. Live objects, collections, and realm instances are
**thread-confined**: that is, they are only valid on the thread on which
they were created. Practically speaking, this means you cannot pass live
instances to other threads. However, Realm offers several
mechanisms for sharing objects across threads. These mechanisms typically require
your code to do some explicit handling to safely pass data across threads.

You can use some of these mechanisms, such as frozen objects or the ThreadSafeReference, to safely use Realm objects and instances
across threads with the `await` keyword. You can also avoid
threading-related issues by marking any asynchronous Realm code with
`@MainActor` to ensure your apps always execute this code on the main
thread.

As a general rule, keep in mind that using Realm in an `await` context
*without* incorporating threading protection may yield inconsistent behavior.
Sometimes, the code may succeed. In other cases, it may throw an error
related to writing on an incorrect thread.

### Perform Background Writes
A commonly-requested use case for asynchronous code is to perform write
operations in the background without blocking the main thread.

Realm has two APIs that allow for performing asynchronous writes:

- The [writeAsync()](https://www.mongodb.com/docs/realm-sdks/swift/latest/Structs/Realm.html#/s:10RealmSwift0A0V10writeAsync_10onCompletes6UInt32Vyyc_ys5Error_pSgcSgtF)
API allows for performing async writes using Swift completion handlers.
- The [asyncWrite()](https://www.mongodb.com/docs/realm-sdks/swift/latest/Structs/Realm.html#/s:10RealmSwift0A0V10asyncWriteyxxyKXEYaKlF)
API allows for performing async writes using Swift async/await syntax.

Both of these APIs allow you to add, update, or delete objects in the
background without using frozen objects or passing a thread-safe reference.

With the `writeAsync()` API, waiting to obtain the write lock and
committing a transaction occur in the background. The write block itself
runs on the calling thread. This provides thread-safety without requiring
you to manually handle frozen objects or passing references across threads.

However, while the write block itself is executed, this does block new
transactions on the calling thread. This means that a large write using
the `writeAsync()` API could block small, quick writes while it executes.

The `asyncWrite()` API suspends the calling task while waiting for its
turn to write rather than blocking the thread. In addition, the actual
I/O to write data to disk is done by a background worker thread. For small
writes, using this function on the main thread may block the main thread
for less time than manually dispatching the write to a background thread.

For more information, including code examples, refer to: Perform a Background Write.

## Tasks and TaskGroups
Swift concurrency provides APIs to manage [Tasks](https://developer.apple.com/documentation/swift/task)
and [TaskGroups](https://developer.apple.com/documentation/swift/taskgroup). The [Swift concurrency
documentation](https://docs.swift.org/swift-book/LanguageGuide/Concurrency.html)
defines a task as a unit of work that can be run asynchronously as part of
your program. Task allows you to specifically define a unit of asynchronous
work. TaskGroup lets you define a collection of Tasks to execute as a unit
under the parent TaskGroup.

Tasks and TaskGroups provide the ability to yield the thread to other
important work or to cancel a long-running task that could be blocking
other operations. To get these benefits, you might be tempted to use Tasks
and TaskGroups to manage realm writes in the background.

However, the thread-confined constraints described in Suspending
Execution with Await above apply in
the Task context. If your Task contains `await` points, subsequent code
might run or resume on a different thread and violate Realm's thread confinement.

You must annotate functions that you run in a Task context with `@MainActor`
to ensure code that accesses Realm only runs on the main thread. This negates
some of the benefits of using Tasks, and may mean this is not a good design
choice for apps that use Realm unless you are using Tasks solely for
networking activities like managing users.

## Actor Isolation
> Seealso:
> The information in this section is applicable to Realm SDK versions earlier
than 10.39.0. Starting in Realm Swift SDK version 10.39.0 and newer,
the SDK supports using Realm with Swift Actors and related async functionality.
>
> For more information, refer to Use Realm with Actors - Swift SDK.
>

Actor isolation provides the perception of confining Realm access to a
dedicated actor, and therefore seems like a safe way to manage Realm
access in an asynchronous context.

However, using Realm in a non-`@MainActor` async function is currently
not supported.

In Swift 5.6, this would often work by coincidence. Execution after an
`await` would continue on whatever thread the awaited thing ran on.
Using `await Realm()` in an async function would result in the code
following that running on the main thread until your next call to an
actor-isolated function.

Swift 5.7 instead hops threads whenever changing actor isolation contexts.
An unisolated async function always runs on a background thread instead.

If you have code which uses `await Realm()` and works in 5.6, marking
the function as `@MainActor` will make it work with Swift 5.7. It will
function how it did - unintentionally - in 5.6.

## Errors Related to Concurrency Code
Most often, the error you see related to accessing Realm through concurrency
code is `Realm accessed from incorrect thread.` This is due to the
thread-isolation issues described on this page.

To avoid threading-related issues in code that uses Swift concurrency features:

- Upgrade to a version of the Realm Swift SDK that supports actor-isolated realms,
and use this as an alternative to manually managing threading. For more
information, refer to Use Realm with Actors - Swift SDK.
- Do not change execution contexts when accessing a realm. If you open a realm
on the main thread to provide data for your UI, annotate subsequent functions
where you access the realm asynchronously with `@MainActor` to ensure it
always runs on the main thread. Remember that `await` marks a suspension
point that could change to a different thread.
- Apps that do not use actor-isolated realms can use the `writeAsync` API to
perform a background write. This manages realm
access in a thread-safe way without requiring you to write specialized code
to do it yourself. This is a special API that outsources aspects of the
write process - where it is safe to do so - to run in an async context.
Unless you are writing to an actor-isolated realm, you do not use this
method with Swift's `async/await` syntax. Use this method synchronously
in your code. Alternately, you can use the `asyncWrite` API with Swift's
`async/await` syntax when awaiting writes to asynchronous realms.
- If you want to explicitly write concurrency code that is not actor-isolated
where accessing a realm is done in a thread-safe way, you can explicitly
pass instances across threads where
applicable to avoid threading-related crashes. This does require a good
understanding of Realm's threading model, as well as being mindful of
Swift concurrency threading behaviors.

## Sendable, Non-Sendable and Thread-Confined Types
The Realm Swift SDK public API contains types that fall into three broad
categories:

- Sendable
- Not Sendable and not thread confined
- Thread-confined

You can share types that are not Sendable and not thread confined between
threads, but you must synchronize them.

Thread-confined types, unless frozen, are confined to an isolation context.
You cannot pass them between these contexts even with synchronization.

---

### Guides Swiftui (`docs/guides/swiftui.md`)

# SwiftUI - Swift SDK
## Overview
The Realm Swift SDK offers features that integrate into SwiftUI.
This documentation provides an overview of those features.

- [Quick Start](swiftui-tutorial.md)
- [Model Data](model-data/define-a-realm-object-model.md)
- [Configure and Open a Realm](configure-and-open-realm.md)
- [React to Changes](react-to-changes.md)
- [Pass Realm Data Between Views](pass-realm-data-between-views.md)
- [Write Data](write.md)
- [Filter Data](filter-data.md)
- [Use Realm with SwiftUI Previews](swiftui-previews.md)

## Requirements
- Xcode project using the SwiftUI "App" template. To use all of the Realm
Swift SDK's SwiftUI features, the minimum iOS target is 15.0. Some features
are compatible with older versions of iOS.
- Install the Swift SDK. Use the most recent version of
the Realm Swift SDK to get all of the features and enhancements for SwiftUI.

---

### Guides Test And Debug (`docs/guides/test-and-debug.md`)

# Test and Debug - Swift SDK
## Testing
### Test Using a Default Realm
The easiest way to use and test Realm-backed applications
is to use the default realm. To avoid overriding application data or
leaking state between tests, set the default realm to a new file for
each test.

```swift
// A base class which each of your Realm-using tests should inherit from rather
// than directly from XCTestCase
class TestCaseBase: XCTestCase {
    override func setUp() {
        super.setUp()

        // Use an in-memory Realm identified by the name of the current test.
        // This ensures that each test can't accidentally access or modify the data
        // from other tests or the application itself, and because they're in-memory,
        // there's nothing that needs to be cleaned up.
        Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name
    }
}

```

### Injecting Realm Instances
Another way to test Realm-related code is to have all the
methods you'd like to test accept a realm instance as an argument. This
enables you to pass in different realms when running the app and when
testing it.

For example, suppose your app has a method to `GET` a user profile
from a JSON API. You want to test that the local profile is properly
created.

### Simplify Testing with Class Projections
> Version added: 10.21.0

If you want to work with a subset of an object's properties for testing,
you can create a class projection.
A class projection is a model abstraction where you can pass through, rename,
or exclude realm object properties. While this feature simplifies view
model implementation, it also simplifies testing with Realm.

> Example:
> This example uses the object models
and the class projection from the
Define and Use Class Projections page.
>
> In this example, we create a realm object using the full object model.
Then, we view retrieve the object as a class projection, working with
only a subset of its properties.
>
> With this class projection, we don't need to access or account for
properties that we don't need to test.
>
> ```swift
> func testWithProjection() {
>     let realm = try! Realm()
>     // Create a Realm object, populate it with values
>     let jasonBourne = Person(value: ["firstName": "Jason",
>                                                        "lastName": "Bourne",
>                                                        "address": [
>                                                         "city": "Zurich",
>                                                         "country": "Switzerland"]])
>     try! realm.write {
>         realm.add(jasonBourne)
>     }
>
>     // Retrieve all class projections of the given type `PersonProjection`
>     // and filter for the first class projection where the `firstName` property
>     // value is "Jason"
>     let person = realm.objects(PersonProjection.self).first(where: { $0.firstName == "Jason" })!
>     // Verify that we have the correct PersonProjection
>     XCTAssert(person.firstName == "Jason")
>     // See that `homeCity` exists as a projection property
>     // Although it is not on the object model
>     XCTAssert(person.homeCity == "Zurich")
>
>     // Change a value on the class projection
>     try! realm.write {
>         person.firstName = "David"
>     }
>
>     // Verify that the projected property's value has changed
>     XCTAssert(person.firstName == "David")
> }
>
> ```
>

### Test Targets
Don't link the Realm framework directly to your test target.
This can cause your tests to fail with an exception message "Object type
'YourObject' is not managed by the Realm." Unlinking Realm
from your test target should resolve this issue.

Compile your model class files in your application or framework targets;
don't add them to your unit test targets. Otherwise, those classes are
duplicated when testing, which can lead to difficult-to-debug issues.

Expose all the code that you need for testing to your unit test
targets. Use the `public` access modifier or [@testable](https://developer.apple.com/library/archive/documentation/DeveloperTools/Conceptual/testing_with_xcode/chapters/04-writing_tests.html).

Since you're using Realm as a dynamic framework, you'll
need to make sure your unit test target can find Realm.
Add the parent path to `RealmSwift.framework` to your unit test's
"Framework Search Paths".

## Debugging
### Debug Using Realm Studio
Realm Studio enables you to open and edit local
realms. It supports Mac, Windows and Linux.

### LLDB
Debugging apps using Realm's Swift API must be done through
the LLDB console.

Although the LLDB script allows inspecting the contents of your realm
variables in Xcode's UI, this doesn't yet work for Swift. Those
variables will show incorrect data. Instead, use LLDB's `po`
command to inspect the contents of data stored in a realm.

## Troubleshooting
### Resolve Build Issues
Some developers experience build issues after installing the Realm Swift SDK via
CocoaPods or Carthage. Common causes of these issues include:

- Installation issues: Initial install failedUsing an unsupported version of the dependency manager
- Build tool issues: Build tools have stale cachesUpdating build tool versions
- Making changes to your project setup, such as: Adding a new targetSharing dependencies across targets

A fix that often clears these issues is to delete derived data
and clean the Xcode build folder.

#### Cocoapods

##### Reset the Cocoapods Integration State
Run these commands in the terminal, in the root of your project:

```bash
pod cache clean Realm
pod cache clean RealmSwift
pod deintegrate || rm -rf Pods
pod install --repo-update --verbose
# Assumes the default DerivedData location:
rm -rf ~/Library/Developer/Xcode/DerivedData
```

##### Clean the Xcode Build Folder
With your project open in Xcode, go to the Product drop-down menu,
and select Clean Build Folder.

#### Carthage

##### Reset Carthage-managed Dependency State
Run these commands in the terminal, in the root of your project:

```bash
rm -rf Carthage
# Assumes default DerivedData location:
rm -rf ~/Library/Developer/Xcode/DerivedData
carthage update
```

##### Clean the Xcode Build Folder
With your project open in Xcode, go to the Product drop-down menu,
and select Clean Build Folder.

### Issues Opening Realm Before Loading the UI
You may open a realm and immediately see crashes with error messages
related to properties being optional or required. Issues with your
object model can cause
these types of crashes. These errors occur after you open a realm,
but before you get to the UI.

Realm has a "schema discovery" phase when a realm opens on the device.
At this time, Realm examines the schema for any objects that it manages.
You can specify that a given realm should manage only a subset
of objects in your
application.

If you see errors related to properties during schema discovery, these are
likely due to schema issues and not issues with data from a specific object.
For example, you may see schema discovery errors if you define a to-one
relationship as required
instead of optional.

To debug these crashes, check the schema you've defined.

You can tell these are schema discovery issues because they occur before
the UI loads. This means that no UI element is attempting to incorrectly
use a property, and there aren't any objects in memory that could have
bad data. If you get errors related to properties *after* the UI loads,
this is probably not due to invalid schema. Instead, those errors are
likely a result of incorrect, wrongly-typed or missing data.

### No Properties are Defined for Model
The Realm Swift SDK uses the Swift language reflection feature to determine
the properties in your model at runtime. If you get a crash similar to
the following, confirm that your project has not disabled reflection metadata:

```shell
Terminating app due to uncaught exception 'RLMException', reason: 'No properties are defined for 'ObjectName'.
```

If you set `SWIFT_REFLECTION_METADATA_LEVEL = none`, Realm cannot
discover children of types, such as properties and enums. Reflection is
enabled by default if your project does not specifically set a level for
this setting.

### Bad Alloc/Not Enough Memory Available
In iOS or iPad devices with little available memory, or where you have a
memory-intensive application that uses multiple realms or many notifications,
you may encounter the following error:

```console
libc++abi: terminating due to an uncaught exception of type std::bad_alloc: std::bad_alloc
```

This error typically indicates that a resource cannot be allocated because
not enough memory is available.

If you are building for iOS 15+ or iPad 15+, you can add the
[Extended Virtual Addressing Entitlement](https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_developer_kernel_extended-virtual-addressing)
to resolve this issue.

Add these keys to your Property List, and set the values to `true`:

```xml
<key>com.apple.developer.kernel.extended-virtual-addressing</key>
<true/>
<key>com.apple.developer.kernel.increased-memory-limit</key>
<true/>
```

### Swift Package Target Cannot be Built Dynamically
> Version changed: 10.49.3

Swift SDK v10.49.3 changed the details for installing the package with
Swift Package Manager (SPM). When you update from an older version of the
package to v10.49.3 or newer, you may get a build error similar to:

```console
Swift package target `Realm` is linked as a static library by `TargetName`
and `Realm`, but cannot be built dynamically because there is a package
product with the same name.
```

To resolve this error, unlink either the `Realm` or the `RealmSwift`
package from your build target. You can do this in Xcode by following these
steps:

1. In your project Targets, select your build target.
2. Go to the Build Phases tab.
3. Expand the Link Binary With Libraries element.
4. Select either `Realm` or `RealmSwift`, and click the Remove items
(-) button to remove the unneeded binary. If you use Swift or Swift
and Objective-C APIs, keep `RealmSwift`. If you use only Objective-C
APIs, keep `Realm`.

Now your target should build without this error.

---

### Guides Use Realm With Actors (`docs/guides/use-realm-with-actors.md`)

# Use Realm with Actors - Swift SDK
Starting with Realm Swift SDK version 10.39.0, Realm supports built-in
functionality for using Realm with Swift Actors. Realm's actor support
provides an alternative to managing threads or dispatch queues to perform
asynchronous work. You can use Realm with actors in a few different ways:

- Work with realm *only* on a specific actor with an actor-isolated realm
- Use Realm across actors based on the needs of your application

You might want to use an actor-isolated realm if you want to restrict all
realm access to a single actor. This negates the need to pass data across
the actor boundary, and can simplify data race debugging.

You might want to use realms across actors in cases where you want to
perform different types of work on different actors. For example, you might
want to read objects on the MainActor but use a background actor for large
writes.

For general information about Swift actors, refer to [Apple's Actor
documentation](https://developer.apple.com/documentation/swift/actor).

## Prerequisites
To use Realm in a Swift actor, your project must:

- Use Realm Swift SDK version 10.39.0 or later
- Use Swift 5.8/Xcode 14.3

In addition, we strongly recommend enabling these settings in your project:

- `SWIFT_STRICT_CONCURRENCY=complete`: enables strict concurrency checking
- `OTHER_SWIFT_FLAGS=-Xfrontend-enable-actor-data-race-checks`: enables
runtime actor data-race detection

## About the Examples on This Page
The examples on this page use the following model:

```swift
class Todo: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var name: String
    @Persisted var owner: String
    @Persisted var status: String
}

```

## Open an Actor-Isolated Realm
You can use the Swift async/await syntax to await opening a realm.

Initializing a realm with `try await Realm()` opens a MainActor-isolated
realm. Alternately, you can explicitly specify an actor when opening a
realm with the `await` syntax.

```swift
@MainActor
func mainThreadFunction() async throws {
    // These are identical: the async init produces a
    // MainActor-isolated Realm if no actor is supplied
    let realm1 = try await Realm()
    let realm2 = try await Realm(actor: MainActor.shared)

    try await useTheRealm(realm: realm1)
}

```

You can specify a default configuration or customize your configuration when
opening an actor-isolated realm:

```swift
@MainActor
func mainThreadFunction() async throws {
    let username = "Galadriel"

    // Customize the default realm config
    var config = Realm.Configuration.defaultConfiguration
    config.fileURL!.deleteLastPathComponent()
    config.fileURL!.appendPathComponent(username)
    config.fileURL!.appendPathExtension("realm")

    // Open an actor-isolated realm with a specific configuration
    let realm = try await Realm(configuration: config, actor: MainActor.shared)

    try await useTheRealm(realm: realm)
}

```

For more general information about configuring a realm, refer to
Configure & Open a Realm.

## Define a Custom Realm Actor
You can define a specific actor to manage Realm in asynchronous contexts.
You can use this actor to manage realm access and perform write operations.

```
/* Detailed source-code truncated for AI context efficiency. */
```

An actor-isolated realm may be used with either local or global actors.

```swift
// A simple example of a custom global actor
@globalActor actor BackgroundActor: GlobalActor {
    static var shared = BackgroundActor()
}

@BackgroundActor
func backgroundThreadFunction() async throws {
    // Explicitly specifying the actor is required for anything that is not MainActor
    let realm = try await Realm(actor: BackgroundActor.shared)
    try await realm.asyncWrite {
        _ = realm.create(Todo.self, value: [
            "name": "Pledge fealty and service to Gondor",
            "owner": "Pippin",
            "status": "In Progress"
        ])
    }
    // Thread-confined Realms would sometimes throw an exception here, as we
    // may end up on a different thread after an `await`
    let todoCount = realm.objects(Todo.self).count
    print("The number of Realm objects is: \(todoCount)")
}

@MainActor
func mainThreadFunction() async throws {
    try await backgroundThreadFunction()
}

```

### Use a Realm Actor Synchronously in an Isolated Function
When a function is confined to a specific actor, you can use the actor-isolated
realm synchronously.

```swift
func createObject(in actor: isolated RealmActor) async throws {
    // Because this function is isolated to this actor, you can use
    // realm synchronously in this context without async/await keywords
    try actor.realm.write {
        actor.realm.create(Todo.self, value: [
            "name": "Keep it secret",
            "owner": "Frodo",
            "status": "In Progress"
        ])
    }
    let taskCount = actor.count
    print("The actor currently has \(taskCount) tasks")
}

let actor = try await RealmActor()

try await createObject(in: actor)

```

### Use a Realm Actor in Async Functions
When a function isn't confined to a specific actor, you can use your Realm actor
with Swift's async/await syntax.

```swift
func createObject() async throws {
    // Because this function is not isolated to this actor,
    // you must await operations completed on the actor
    try await actor.createTodo(name: "Take the ring to Mount Doom", owner: "Frodo", status: "In Progress")
    let taskCount = await actor.count
    print("The actor currently has \(taskCount) tasks")
}

let actor = try await RealmActor()

try await createObject()

```

## Write to an Actor-Isolated Realm
Actor-isolated realms can use Swift async/await syntax for asynchronous
writes. Using `try await realm.asyncWrite { ... }` suspends the current task,
acquires the write lock without blocking the current thread, and then invokes
the block. Realm writes the data to disk on a background thread and resumes
the task when that completes.

This function from the example `RealmActor` defined above shows how you might
write to an actor-isolated realm:

```swift
func createTodo(name: String, owner: String, status: String) async throws {
    try await realm.asyncWrite {
        realm.create(Todo.self, value: [
            "_id": ObjectId.generate(),
            "name": name,
            "owner": owner,
            "status": status
        ])
    }
}

```

And you might perform this write using Swift's async syntax:

```swift
func createObject() async throws {
    // Because this function is not isolated to this actor,
    // you must await operations completed on the actor
    try await actor.createTodo(name: "Take the ring to Mount Doom", owner: "Frodo", status: "In Progress")
    let taskCount = await actor.count
    print("The actor currently has \(taskCount) tasks")
}

let actor = try await RealmActor()

try await createObject()

```

This does not block the calling thread while waiting to write. It does
not perform I/O on the calling thread. For small writes, this is safe to
use from `@MainActor` functions without blocking the UI. Writes that
negatively impact your app's performance due to complexity and/or platform
resource constraints may still benefit from being done on a background thread.

Asynchronous writes are only supported for actor-isolated Realms or in
`@MainActor` functions.

## Pass Realm Data Across the Actor Boundary
Realm objects are not [Sendable](https://developer.apple.com/documentation/swift/sendable),
and cannot cross the actor boundary directly. To pass Realm data across
the actor boundary, you have two options:

- Pass a `ThreadSafeReference` to or from the actor
- Pass other types that *are* Sendable, such as passing values directly
or by creating structs to pass across actor boundaries

### Pass a ThreadSafeReference
You can create a `ThreadSafeReference` on an
actor where you have access to the object. In this case, we create a
`ThreadSafeReference` on the `MainActor`. Then, pass the `ThreadSafeReference` to the destination actor.

```swift
// We can pass a thread-safe reference to an object to update it on a different actor.
let todo = todoCollection.where {
    $0.name == "Arrive safely in Bree"
}.first!
let threadSafeReferenceToTodo = ThreadSafeReference(to: todo)
try await backgroundActor.deleteTodo(tsrToTodo: threadSafeReferenceToTodo)

```

On the destination actor, you must `resolve()` the reference within a
write transaction before you can use it. This retrieves a version of the
object local to that actor.

```swift
actor BackgroundActor {
    public func deleteTodo(tsrToTodo tsr: ThreadSafeReference<Todo>) throws {
        let realm = try! Realm()
        try realm.write {
            // Resolve the thread safe reference on the Actor where you want to use it.
            // Then, do something with the object.
            let todoOnActor = realm.resolve(tsr)
            realm.delete(todoOnActor!)
        }
    }
}

```

> Important:
> You must resolve a `ThreadSafeReference` exactly once. Otherwise,
the source realm remains pinned until the reference gets
deallocated. For this reason, `ThreadSafeReference` should be
short-lived.
>
> If you may need to share the same realm object across actors more than
once, you may prefer to share the primary key
and query for it on
the actor where you want to use it. Refer to the "Pass a Primary Key
and Query for the Object on Another Actor" section on this page for an example.
>

### Pass a Sendable Type
While Realm objects are not Sendable, you can work around this by passing
Sendable types across actor boundaries. You can use a few strategies to
pass Sendable types and work with data across actor boundaries:

- Pass Sendable Realm types or primitive values instead of complete Realm objects
- Pass an object's primary key and query for the object on another actor
- Create a Sendable representation of your Realm object, such as a struct

#### Pass Sendable Realm Types and Primitive Values
If you only need a piece of information from the Realm object, such as a
`String` or `Int`, you can pass the value directly across actors instead
of passing the Realm object. For a full list of which Realm types are Sendable,
refer to Sendable, Non-Sendable and Thread-Confined Types.

```swift
@MainActor
func mainThreadFunction() async throws {
    // Create an object in an actor-isolated realm.
    // Pass primitive data to the actor instead of
    // creating the object here and passing the object.
    let actor = try await RealmActor()
    try await actor.createTodo(name: "Prepare fireworks for birthday party", owner: "Gandalf", status: "In Progress")

    // Later, get information off the actor-confined realm
    let todoOwner = await actor.getTodoOwner(forTodoNamed: "Prepare fireworks for birthday party")
}

```

#### Pass a Primary Key and Query for the Object on Another Actor
If you want to use a Realm object on another actor, you can share the
primary key and
query for it on the actor
where you want to use it.

```swift
// Execute code on a specific actor - in this case, the @MainActor
@MainActor
func mainThreadFunction() async throws {
    // Create an object off the main actor
    func createObject(in actor: isolated BackgroundActor) async throws -> ObjectId {
        let realm = try await Realm(actor: actor)
        let newTodo = try await realm.asyncWrite {
            return realm.create(Todo.self, value: [
                "name": "Pledge fealty and service to Gondor",
                "owner": "Pippin",
                "status": "In Progress"
            ])
        }

        // Share the todo's primary key so we can easily query for it on another actor
        return newTodo._id
    }

    // Initialize an actor where you want to perform background work
    let actor = BackgroundActor()
    let newTodoId = try await createObject(in: actor)
    let realm = try await Realm()
    let todoOnMainActor = realm.object(ofType: Todo.self, forPrimaryKey: newTodoId)
}

```

#### Create a Sendable Representation of Your Object
If you need to work with more than a simple value, but don't want the
overhead of passing around `ThreadSafeReferences` or querying objects on
different actors, you can create a struct or other Sendable representation
of your data to pass across the actor boundary.

For example, your actor might have a function that creates a struct
representation of the Realm object.

```swift
struct TodoStruct {
    var id: ObjectId
    var name, owner, status: String
}

func getTodoAsStruct(forTodoNamed name: String) -> TodoStruct {
    let todo = realm.objects(Todo.self).where {
        $0.name == name
    }.first!
    return TodoStruct(id: todo._id, name: todo.name, owner: todo.owner, status: todo.status)
}

```

Then, you can call a function to get the data as a struct on another actor.

```swift
@MainActor
func mainThreadFunction() async throws {
    // Create an object in an actor-isolated realm.
    let actor = try await RealmActor()
    try await actor.createTodo(name: "Leave the ring on the mantle", owner: "Bilbo", status: "In Progress")

    // Get information as a struct or other Sendable type.
    let todoAsStruct = await actor.getTodoAsStruct(forTodoNamed: "Leave the ring on the mantle")
}

```

## Observe Notifications on a Different Actor
You can observe notifications on an actor-isolated realm using Swift's
async/await syntax.

Calling `await object.observe(on: Actor)` or
`await collection.observe(on: Actor)` registers a block to be called
each time the object or collection changes.

The SDK asynchronously calls the block on the given actor's executor.

For write transactions performed on different threads or in different
processes, the SDK calls the block when the realm is (auto)refreshed
to a version including the changes. For local writes, the SDK calls the block
at some point in the future after the write transaction is committed.

Like other Realm notifications, you can
only observe objects or collections managed by a realm. You must retain the
returned token for as long as you want to watch for updates.

If you need to manually advance the state of an observed realm on the main
thread or on another actor, call `await realm.asyncRefresh()`.
This updates the realm and outstanding objects managed by the Realm to point to
the most recent data and deliver any applicable notifications.

### Observation Limitations
You *cannot* call the `.observe()` method:

- During a write transaction
- When the containing realm is read-only
- On an actor-confined realm from outside the actor

### Register a Collection Change Listener
The SDK calls a collection notification block after each write transaction which:

- Deletes an object from the collection.
- Inserts an object into the collection.
- Modifies any of the managed properties of an object in the collection. This
includes self-assignments that set a property to its existing value.

> Important:
> In collection notification handlers, always apply changes
in the following order: deletions, insertions, then
modifications. Handling insertions before deletions may
result in unexpected behavior.
>

These notifications provide information about the actor on which the change
occurred. Like non-actor-isolated collection notifications, they also provide
a `change` parameter that reports which objects are deleted, added, or
modified during the write transaction. This `RealmCollectionChange`
resolves to an array of index paths that you can pass to a `UITableView`'s
batch update methods.

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Register an Object Change Listener
The SDK calls an object notification block after each write transaction which:

- Deletes the object.
- Modifies any of the managed properties of the object. This includes
self-assignments that set a property to its existing value.

The block is passed a copy of the object isolated to the requested actor,
along with information about what changed. This object can be safely used
on that actor.

By default, only direct changes to the object's properties produce notifications.
Changes to linked objects do not produce notifications. If a non-nil, non-empty
keypath array is passed in, only changes to the properties identified by those
keypaths produce change notifications. The keypaths may traverse link
properties to receive information about changes to linked objects.

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Guides Xcode Playgrounds (`docs/guides/xcode-playgrounds.md`)

# Use Realm in Xcode Playgrounds
## Prerequisites
You can only use Swift packages within Xcode projects that have at least one
scheme and target. To use Realm in Xcode Playgrounds, you must first have
an Xcode project where you have Installed the Swift SDK.

## Create a Playground

Within a project, go to File > New > Playground. Select the type of
Playground you want. For this example, we've used a Blank iOS
Playground.

Name and save the playground in the root of your
project. Be sure to add it to the project.

You should see your new Playground in your Project navigator.

## Import Realm
Add the following import statement to use Realm in the playground:

```swift
import RealmSwift

```

## Experiment with Realm
Experiment with Realm. For this example, we'll:

- Define a new Realm object type
- Create a new object of that type and write it to realm
- Query objects of the type, and filter them

```swift
class Drink: Object {
    @Persisted var name = ""
    @Persisted var rating = 0
    @Persisted var source = ""
    @Persisted var drinkType = ""
}

let drink = Drink(value: ["name": "Los Cabellos", "rating": 10, "source": "AeroPress", "drinkType": "Coffee"])

let realm = try! Realm(configuration: config)

try! realm.write {
    realm.add(drink)
}

let drinks = realm.objects(Drink.self)

let coffeeDrinks = drinks.where {
    $0.drinkType == "Coffee"
}

print(coffeeDrinks.first?.name)
```

## Managing the Realm File in Your Playground
When you work with a default realm
in a Playground, you might run into a situation where you need to delete the
realm. For example, if you are experimenting with an object type and add
properties to the object, you may get an error that you must migrate the
realm.

You can specify `Realm.configuration` details to open the file at a specific
path, and delete the realm if it exists at the path.

```swift
var config = Realm.Configuration()

config.fileURL!.deleteLastPathComponent()
config.fileURL!.appendPathComponent("playgroundRealm")
config.fileURL!.appendPathExtension("realm")

if Realm.fileExists(for: config) {
    try Realm.deleteFiles(for: config)
    print("Successfully deleted existing realm at path: \(config.fileURL!)")
} else {
    print("No file currently exists at path")
}
```

Alternately, you can open the realm in-memory only, or use the
`deleteRealmIfMigrationNeeded`
method to automatically delete a realm when migration is needed.

---

### Guides Crud Create (`docs/guides/crud/create.md`)

# CRUD - Create - Swift SDK
## Create a New Object
### About The Examples On This Page
The examples on this page use the following models:

#### Objective-C

```objectivec
// DogToy.h
@interface DogToy : RLMObject
@property NSString *name;
@end

// Dog.h
@interface Dog : RLMObject
@property NSString *name;
@property int age;
@property NSString *color;

// To-one relationship
@property DogToy *favoriteToy;

@end

// Enable Dog for use in RLMArray
RLM_COLLECTION_TYPE(Dog)

// Person.h
// A person has a primary key ID, a collection of dogs, and can be a member of multiple clubs.
@interface Person : RLMObject
@property int _id;
@property NSString *name;

// To-many relationship - a person can have many dogs
@property RLMArray<Dog *><Dog> *dogs;

// Inverse relationship - a person can be a member of many clubs
@property (readonly) RLMLinkingObjects *clubs;
@end

RLM_COLLECTION_TYPE(Person)

// DogClub.h
@interface DogClub : RLMObject
@property NSString *name;
@property RLMArray<Person *><Person> *members;
@end

// Dog.m
@implementation Dog
@end

// DogToy.m
@implementation DogToy
@end

// Person.m
@implementation Person
// Define the primary key for the class
+ (NSString *)primaryKey {
    return @"_id";
}

// Define the inverse relationship to dog clubs
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"clubs": [RLMPropertyDescriptor descriptorWithClass:DogClub.class propertyName:@"members"],
    };
}
@end

// DogClub.m
@implementation DogClub
@end

```

#### Swift

```swift
class DogToy: Object {
    @Persisted var name = ""
}

class Dog: Object {
    @Persisted var name = ""
    @Persisted var age = 0
    @Persisted var color = ""
    @Persisted var currentCity = ""
    @Persisted var citiesVisited: MutableSet<String>
    @Persisted var companion: AnyRealmValue

    // To-one relationship
    @Persisted var favoriteToy: DogToy?

    // Map of city name -> favorite park in that city
    @Persisted var favoriteParksByCity: Map<String, String>
}

class Person: Object {
    @Persisted(primaryKey: true) var id = 0
    @Persisted var name = ""

    // To-many relationship - a person can have many dogs
    @Persisted var dogs: List<Dog>

    // Embed a single object.
    // Embedded object properties must be marked optional.
    @Persisted var address: Address?

    convenience init(name: String, address: Address) {
        self.init()
        self.name = name
        self.address = address
    }
}

class Address: EmbeddedObject {
    @Persisted var street: String?
    @Persisted var city: String?
    @Persisted var country: String?
    @Persisted var postalCode: String?
}

```

### Create an Object
#### Objective-C

To add an object to a realm, instantiate it as you would any other
object and then pass it to `-[RLMRealm addObject:]` inside
of a write transaction.

```objectivec
// Get the default realm.
// You only need to do this once per thread.
RLMRealm *realm = [RLMRealm defaultRealm];

// Instantiate the class.
Dog *dog = [[Dog alloc] init];
dog.name = @"Max";
dog.age = 5;

// Open a thread-safe transaction.
[realm transactionWithBlock:^() {
    // Add the instance to the realm.
    [realm addObject:dog];
}];

```

#### Swift

To add an object to a realm, instantiate it as you would any other
object and then pass it to `Realm.add(_:update:)`
inside of a write transaction.

```swift
// Instantiate the class and set its values.
let dog = Dog()
dog.name = "Rex"
dog.age = 10

// Get the default realm. You only need to do this once per thread.
let realm = try! Realm()
// Open a thread-safe transaction.
try! realm.write {
    // Add the instance to the realm.
    realm.add(dog)
}

```

### Initialize Objects with a Value
You can initialize an object by passing an initializer value to
`Object.init(value:)`.
The initializer value can be a [key-value coding](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/)
compliant object, a dictionary, or an array containing one element for
each managed property.

> Note:
> When using an array as an initializer value, you must include all
properties in the same order as they are defined in the model.
>

#### Objective-C

```objectivec
// (1) Create a Dog object from a dictionary
Dog *myDog = [[Dog alloc] initWithValue:@{@"name" : @"Pluto", @"age" : @3}];

// (2) Create a Dog object from an array
Dog *myOtherDog = [[Dog alloc] initWithValue:@[@"Pluto", @3]];

RLMRealm *realm = [RLMRealm defaultRealm];

// Add to the realm with transaction
[realm transactionWithBlock:^() {
    [realm addObject:myDog];
    [realm addObject:myOtherDog];
}];

```

#### Swift

```swift
// (1) Create a Dog object from a dictionary
let myDog = Dog(value: ["name": "Pluto", "age": 3])

// (2) Create a Dog object from an array
let myOtherDog = Dog(value: ["Fido", 5])

let realm = try! Realm()
// Add to the realm inside a transaction
try! realm.write {
    realm.add([myDog, myOtherDog])
}

```

You can even initialize related or
embedded objects by nesting initializer
values:

#### Objective-C

```objectivec
// Instead of using pre-existing dogs...
Person *aPerson = [[Person alloc]
    initWithValue:@[@123, @"Jane", @[aDog, anotherDog]]];

// ...we can create them inline
Person *anotherPerson = [[Person alloc]
    initWithValue:@[@123, @"Jane", @[@[@"Buster", @5], @[@"Buddy", @6]]]];

```

#### Swift

```swift
// Instead of using pre-existing dogs...
let aPerson = Person(value: [123, "Jane", [aDog, anotherDog]])

// ...we can create them inline
let anotherPerson = Person(value: [123, "Jane", [["Buster", 5], ["Buddy", 6]]])

```

#### Some Property Types are Only Mutable in a Write Transaction
Some property types are only mutable in a write transaction. For example,
you can instantiate an object with a MutableSet
property, but you can only set that property's value in a write transaction.
You cannot initialize the object with a value for that property unless
you do so inside a write transaction.

### Create an Object with JSON
Realm does not directly support JSON, but you can use
[JSONSerialization.jsonObject(with:options:)](https://developer.apple.com/documentation/foundation/jsonserialization/1415493-jsonobject) to
convert JSON into a value that you can pass to
`Realm.create(_:value:update:)`.

#### Objective-C

```objectivec
// Specify a dog toy in JSON
NSData *data = [@"{\"name\": \"Tennis ball\"}" dataUsingEncoding: NSUTF8StringEncoding];
RLMRealm *realm = [RLMRealm defaultRealm];

// Insert from NSData containing JSON
[realm transactionWithBlock:^{
    id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
    [DogToy createInRealm:realm withValue:json];
}];

```

#### Swift

```swift
// Specify a dog toy in JSON
let data = "{\"name\": \"Tennis ball\"}".data(using: .utf8)!
let realm = try! Realm()
// Insert from data containing JSON
try! realm.write {
    let json = try! JSONSerialization.jsonObject(with: data, options: [])
    realm.create(DogToy.self, value: json)
}

```

Nested objects or arrays in the JSON map to to-one or to-many relationships.

The JSON property names and types must match the destination
object schema exactly. For example:

- `float` properties must be initialized with float-backed `NSNumbers`.
- `Date` and `Data` properties cannot be inferred from strings. Convert them to the appropriate type before passing to `Realm.create(_:value:update:)`.
- Required properties cannot be `null` or missing in the JSON.

Realm ignores any properties in the JSON not defined in the
object schema.

> Tip:
> If your JSON schema doesn't exactly align with your Realm objects,
consider using a third-party framework to transform your JSON. There
are many model mapping frameworks that work with Realm.
See a [partial list in the realm-swift repository](https://github.com/realm/realm-swift/issues/694#issuecomment-144785299).
>

### Create an Embedded Object
To create an embedded object, assign an instance of the embedded object
to a parent object's property:

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
    Address *address = [[Address alloc] init];
    address.street = @"123 Fake St.";
    address.city = @"Springfield";
    address.country = @"USA";
    address.postalCode = @"90710";

    Contact *contact = [Contact contactWithName:@"Nick Riviera"];

    // Assign the embedded object property
    contact.address = address;

    [realm addObject:contact];

    NSLog(@"Added contact: %@", contact);
}];

```

#### Swift

```swift
// Open the default realm
let realm = try! Realm()

try! realm.write {
    let address = Address()
    address.street = "123 Fake St"
    address.city = "Springfield"
    address.country = "USA"
    address.postalCode = "90710"
    let contact = Person(name: "Nick Riviera", address: address)
    realm.add(contact)
}

```

### Create an Object with a Map Property
When you create an object that has a `map property`, you can set the values for keys in a few ways:

- Set keys and values on the object and then add the object to the realm
- Set the object's keys and values directly inside a write transaction
- Use key-value coding to set or update keys and values inside a write transaction

```swift
let realm = try! Realm()
// Record a dog's name and current city
let dog = Dog()
dog.name = "Wolfie"
dog.currentCity = "New York"
// Set map values
dog.favoriteParksByCity["New York"] = "Domino Park"
// Store the data in a realm
try! realm.write {
    realm.add(dog)
    // You can also set map values inside a write transaction
    dog.favoriteParksByCity["Chicago"] = "Wrigley Field"
    dog.favoriteParksByCity.setValue("Bush Park", forKey: "Ottawa")
}

```

Realm disallows the use of `.` or `$` characters in map keys.
You can use percent encoding and decoding to store a map key that contains
one of these disallowed characters.

```
// Percent encode . or $ characters to use them in map keys
let mapKey = "New York.Brooklyn"
let encodedMapKey = "New York%2EBrooklyn"

```

### Create an Object with a MutableSet Property
You can create objects that contain `MutableSet` properties as you would any Realm object, but you
can only mutate a MutableSet within a write transaction. This means you can
only set the value(s) of a mutable set property within a write transaction.

```swift
let realm = try! Realm()

// Record a dog's name and current city
let dog = Dog()
dog.name = "Maui"
dog.currentCity = "New York"

// Store the data in a realm. Add the dog's current city
// to the citiesVisited MutableSet
try! realm.write {
    realm.add(dog)
    // You can only mutate the MutableSet in a write transaction.
    // This means you can't set values at initialization, but must do it during a write.
    dog.citiesVisited.insert(dog.currentCity)
}

// You can also add multiple items to the set.
try! realm.write {
    dog.citiesVisited.insert(objectsIn: ["Boston", "Chicago"])
}

print("\(dog.name) has visited: \(dog.citiesVisited)")

```

### Create an Object with an AnyRealmValue Property
When you create an object with an AnyRealmValue property, you must specify the type of the value you store in
the property. The Realm Swift SDK provides an `AnyRealmValue enum` that iterates through all of the types the
AnyRealmValue can store.

Later, when you read an AnyRealmValue,
you must check the type before you do anything with the value.

```swift
// Create a Dog object and then set its properties
let myDog = Dog()
myDog.name = "Rex"
// This dog has no companion.
// You can set the field's type to "none", which represents `nil`
myDog.companion = .none

// Create another Dog whose companion is a cat.
// We don't have a Cat object, so we'll use a string to describe the companion.
let theirDog = Dog()
theirDog.name = "Wolfie"
theirDog.companion = .string("Fluffy the Cat")

// Another dog might have a dog as a companion.
// We do have an object that can represent that, so we can specify the
// type is a Dog object, and even set the object's value.
let anotherDog = Dog()
anotherDog.name = "Fido"
// Note: this sets Spot as a companion of Fido, but does not set
// Fido as a companion of Spot. Spot has no companion in this instance.
anotherDog.companion = .object(Dog(value: ["name": "Spot"]))

// Add the dogs to the realm
let realm = try! Realm()
try! realm.write {
    realm.add([myDog, theirDog, anotherDog])
}
// After adding these dogs to the realm, we now have 4 dog objects.
let dogs = realm.objects(Dog.self)
XCTAssertEqual(dogs.count, 4)

```

## Create an Object Asynchronously
You can use Swift concurrency features to write asynchronously to an
actor-isolated realm.

This function from the example `RealmActor` defined on the
Use Realm with Actors page shows how you might
write to an actor-isolated realm:

```swift
func createTodo(name: String, owner: String, status: String) async throws {
    try await realm.asyncWrite {
        realm.create(Todo.self, value: [
            "_id": ObjectId.generate(),
            "name": name,
            "owner": owner,
            "status": status
        ])
    }
}

```

And you might perform this write using Swift's async syntax:

```swift
func createObject() async throws {
    // Because this function is not isolated to this actor,
    // you must await operations completed on the actor
    try await actor.createTodo(name: "Take the ring to Mount Doom", owner: "Frodo", status: "In Progress")
    let taskCount = await actor.count
    print("The actor currently has \(taskCount) tasks")
}

let actor = try await RealmActor()

try await createObject()

```

This operation does not block or perform I/O on the calling thread. For
more information about writing to realm using Swift concurrency features,
refer to Use Realm with Actors - Swift SDK.

## Copy an Object to Another Realm
#### Objective-C

To copy an object from one realm to another, pass the original
object to `+[RLMObject createInRealm:withValue:]`:

```objectivec
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
configuration.inMemoryIdentifier = @"first realm";
RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration error:nil];

[realm transactionWithBlock:^{
    Dog *dog = [[Dog alloc] init];
    dog.name = @"Wolfie";
    dog.age = 1;
    [realm addObject:dog];
}];

// Later, fetch the instance we want to copy
Dog *wolfie = [[Dog objectsInRealm:realm where:@"name == 'Wolfie'"] firstObject];

// Open the other realm
RLMRealmConfiguration *otherConfiguration = [RLMRealmConfiguration defaultConfiguration];
otherConfiguration.inMemoryIdentifier = @"second realm";
RLMRealm *otherRealm = [RLMRealm realmWithConfiguration:otherConfiguration error:nil];
[otherRealm transactionWithBlock:^{
    // Copy to the other realm
    Dog *wolfieCopy = [[wolfie class] createInRealm:otherRealm withValue:wolfie];
    wolfieCopy.age = 2;

    // Verify that the copy is separate from the original
    XCTAssertNotEqual(wolfie.age, wolfieCopy.age);
}];

```

#### Swift

To copy an object from one realm to another, pass the original
object to `Realm.create(_:value:update:):`:

```swift
let realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "first realm"))

try! realm.write {
    let dog = Dog()
    dog.name = "Wolfie"
    dog.age = 1
    realm.add(dog)
}

// Later, fetch the instance we want to copy
let wolfie = realm.objects(Dog.self).first(where: { $0.name == "Wolfie" })!

// Open the other realm
let otherRealm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "second realm"))
try! otherRealm.write {
    // Copy to the other realm
    let wolfieCopy = otherRealm.create(type(of: wolfie), value: wolfie)
    wolfieCopy.age = 2

    // Verify that the copy is separate from the original
    XCTAssertNotEqual(wolfie.age, wolfieCopy.age)
}

```

> Important:
> The `create` methods do not support handling cyclical object
graphs. Do not pass in an object containing relationships involving
objects that refer back to their parents, either directly or
indirectly.
>

---

### Guides Crud Crud (`docs/guides/crud/crud.md`)

# CRUD - Swift SDK
## Write Transactions
Realm uses a highly efficient storage engine
to persist objects. You can **create** objects in a realm,
**update** objects in a realm, and eventually **delete**
objects from a realm. Because these operations modify the
state of the realm, we call them writes.

Realm handles writes in terms of **transactions**. A
transaction is a list of read and write operations that
Realm treats as a single indivisible operation. In other
words, a transaction is *all or nothing*: either all of the
operations in the transaction succeed or none of the
operations in the transaction take effect.

All writes must happen in a transaction.

A realm allows only one open transaction at a time. Realm
blocks other writes on other threads until the open
transaction is complete. Consequently, there is no race
condition when reading values from the realm within a
transaction.

When you are done with your transaction, Realm either
**commits** it or **cancels** it:

- When Realm **commits** a transaction, Realm writes
all changes to disk.
- When Realm **cancels** a write transaction or an operation in
the transaction causes an error, all changes are discarded
(or "rolled back").

### Run a Transaction
The Swift SDK represents each transaction as a callback function
that contains zero or more read and write operations. To run
a transaction, define a transaction callback and pass it to
the realm's `write` method. Within this callback, you are
free to create, read, update, and delete on the realm. If
the code in the callback throws an exception when Realm runs
it, Realm cancels the transaction. Otherwise, Realm commits
the transaction immediately after the callback.

> Important:
> Since transactions block each other, it is best to avoid
opening transactions on both the UI thread and a
background thread. If a background transaction
blocks your UI thread's transaction, your app may appear
unresponsive.
>

> Example:
> The following code shows how to run a transaction with
the realm's write method. If the code in the callback
throws an exception, Realm cancels the transaction.
Otherwise, Realm commits the transaction.
>
> #### Objective-C
>
> ```objectivec
> // Open the default realm.
> RLMRealm *realm = [RLMRealm defaultRealm];
>
> // Open a thread-safe transaction.
> [realm transactionWithBlock:^() {
>     // ... Make changes ...
>     // Realm automatically cancels the transaction in case of exception.
>     // Otherwise, Realm automatically commits the transaction at the
>     // end of the code block.
> }];
>
> ```
>
>
> #### Swift
>
> ```swift
> // Open the default realm.
> let realm = try! Realm()
>
> // Prepare to handle exceptions.
> do {
>     // Open a thread-safe transaction.
>     try realm.write {
>         // Make any writes within this code block.
>         // Realm automatically cancels the transaction
>         // if this code throws an exception. Otherwise,
>         // Realm automatically commits the transaction
>         // after the end of this code block.
>     }
> } catch let error as NSError {
>     // Failed to write to realm.
>     // ... Handle error ...
> }
>
> ```
>
>

## Interface-Driven Writes
Realm always delivers notifications asynchronously, so they
never block the UI thread. However, there are situations when the UI
must reflect changes instantly. If you update the UI directly at the
same time as the write, the eventual notification could double that
update. This could lead to your app crashing due to inconsistent state
between the UI and the backing data store. To avoid this, you can write
without sending a notification to a specific handler. We call this type
of transaction an **interface-driven write**.

> Example:
> Say we decide to manage a table view's data source manually, because
our app design requires an instantaneous response to UI-driven table
updates. As soon as a user adds an item to the table view, we insert
it to our data source, which writes to the realm but also
immediately kicks off the animation. However, when Realm
delivers the change notification for this insertion a little later,
it indicates that an object has been added. But we already updated
the table view for it! Rather than writing complicated code to handle
this case, we can use interface-driven writes to prevent a specific
notification handler from firing for that specific write.
>

Interface-driven writes, also known as silent writes, are especially
useful when using fine-grained collection notifications. While you use
interface-driven writes for the current user's updates and update the UI
immediately, the sync process can use standard notifications to update
the UI.

---

### Guides Crud Delete (`docs/guides/crud/delete.md`)

# CRUD - Delete - Swift SDK
## Delete Realm Objects
Deleting Realm Objects must occur within write transactions. For
more information about write transactions, see: Transactions.

If you want to delete the Realm file itself, see: Delete a Realm.

> Important:
> You cannot access or modify an object after you have deleted it from
a realm. If you try to use a deleted object, Realm throws an
error.
>

### About The Examples On This Page
The examples on this page use the following models:

#### Objective-C

```objectivec
// DogToy.h
@interface DogToy : RLMObject
@property NSString *name;
@end

// Dog.h
@interface Dog : RLMObject
@property NSString *name;
@property int age;
@property NSString *color;

// To-one relationship
@property DogToy *favoriteToy;

@end

// Enable Dog for use in RLMArray
RLM_COLLECTION_TYPE(Dog)

// Person.h
// A person has a primary key ID, a collection of dogs, and can be a member of multiple clubs.
@interface Person : RLMObject
@property int _id;
@property NSString *name;

// To-many relationship - a person can have many dogs
@property RLMArray<Dog *><Dog> *dogs;

// Inverse relationship - a person can be a member of many clubs
@property (readonly) RLMLinkingObjects *clubs;
@end

RLM_COLLECTION_TYPE(Person)

// DogClub.h
@interface DogClub : RLMObject
@property NSString *name;
@property RLMArray<Person *><Person> *members;
@end

// Dog.m
@implementation Dog
@end

// DogToy.m
@implementation DogToy
@end

// Person.m
@implementation Person
// Define the primary key for the class
+ (NSString *)primaryKey {
    return @"_id";
}

// Define the inverse relationship to dog clubs
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"clubs": [RLMPropertyDescriptor descriptorWithClass:DogClub.class propertyName:@"members"],
    };
}
@end

// DogClub.m
@implementation DogClub
@end

```

#### Swift

```swift
class Dog: Object {
    @Persisted var name = ""
    @Persisted var age = 0
    @Persisted var color = ""
    @Persisted var currentCity = ""
    @Persisted var citiesVisited: MutableSet<String>
    @Persisted var companion: AnyRealmValue

    // Map of city name -> favorite park in that city
    @Persisted var favoriteParksByCity: Map<String, String>
}

```

### Delete an Object
#### Objective-C

To delete an object from a realm, pass the object to
`-[RLMRealm deleteObject:]`
inside of a write transaction.

```objectivec
[realm transactionWithBlock:^() {
    // Delete the instance from the realm.
    [realm deleteObject:dog];
}];

```

#### Swift

To delete an object from a realm, pass the object to
`Realm.delete(_:)`
inside of a write transaction.

```swift
// Previously, we've added a dog object to the realm.
let dog = Dog(value: ["name": "Max", "age": 5])

let realm = try! Realm()
try! realm.write {
    realm.add(dog)
}

// Delete the instance from the realm.
try! realm.write {
    realm.delete(dog)
}

```

### Delete Multiple Objects
#### Swift

> Version added: 10.19.0

To delete a collection of objects from a realm, pass the
collection to `Realm.delete(_:)`
inside of a write transaction.

```swift
let realm = try! Realm()
try! realm.write {
    // Find dogs younger than 2 years old.
    let puppies = realm.objects(Dog.self).where {
        $0.age < 2
    }

    // Delete the objects in the collection from the realm.
    realm.delete(puppies)
}

```

#### Swift Nspredicate

To delete a collection of objects from a realm, pass the
collection to `Realm.delete(_:)`
inside of a write transaction.

```swift
let realm = try! Realm()
try! realm.write {
    // Find dogs younger than 2 years old.
    let puppies = realm.objects(Dog.self).filter("age < 2")

    // Delete the objects in the collection from the realm.
    realm.delete(puppies)
}

```

#### Objective-C

To delete a collection of objects from a realm, pass the
collection to `-[Realm deleteObjects:]`
inside of a write transaction.

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

[realm transactionWithBlock:^() {
    // Find dogs younger than 2 years old.
    RLMResults<Dog *> *puppies = [Dog objectsInRealm:realm where:@"age < 2"];

    // Delete all objects in the collection from the realm.
    [realm deleteObjects:puppies];
}];

```

### Delete an Object and Its Related Objects
Sometimes, you want to delete related objects when you delete the parent
object. We call this a **chaining delete**. Realm does not delete
the related objects for you. If you do not delete the objects yourself,
they remain orphaned in your realm. Whether or not this is a problem
depends on your application's needs.

The best way to delete dependent objects is to iterate through
the dependencies and delete them before deleting the parent object.

#### Objective-C

```objectivec
[realm transactionWithBlock:^() {
    // Delete Ali's dogs.
    [realm deleteObjects:[ali dogs]];
    // Delete Ali.
    [realm deleteObject:ali];
}];

```

#### Swift

```swift
let person = realm.object(ofType: Person.self, forPrimaryKey: 1)!
try! realm.write {
    // Delete the related collection
    realm.delete(person.dogs)
    realm.delete(person)
}

```

### Delete All Objects of a Specific Type
#### Objective-C

To delete all objects of a given object type from a realm, pass
the result of [+[YourRealmObjectClass
allObjectsInRealm:]]
to `-[Realm deleteObjects:]`
inside of a write transaction. Replace `YourRealmObjectClass`
with your Realm object class name.

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

[realm transactionWithBlock:^() {
    // Delete all instances of Dog from the realm.
    RLMResults<Dog *> *allDogs = [Dog allObjectsInRealm:realm];
    [realm deleteObjects:allDogs];
}];

```

#### Swift

To delete all objects of a given object type from a realm, pass
the result of `Realm.objects(_)`
for the type you wish to delete to `Realm.delete(_:)`
inside of a write transaction.

```swift
let realm = try! Realm()

try! realm.write {
    // Delete all instances of Dog from the realm.
    let allDogs = realm.objects(Dog.self)
    realm.delete(allDogs)
}

```

### Delete All Objects in a Realm
#### Objective-C

To delete all objects from the realm, call [-[RLMRealm
deleteAllObjects]]
inside of a write transaction. This clears the realm of all object
instances but does not affect the realm's schema.

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

[realm transactionWithBlock:^() {
    // Delete all objects from the realm.
    [realm deleteAllObjects];
}];

```

#### Swift

To delete all objects from the realm, call
`Realm.deleteAll()` inside of a
write transaction. This clears the realm of all object instances
but does not affect the realm's schema.

```swift
let realm = try! Realm()

try! realm.write {
    // Delete all objects from the realm.
    realm.deleteAll()
}

```

### Delete Map Keys/Values
You can delete `map` entries in a few ways:

- Use `removeObject(for:)` to remove the key and the value
- If the dictionary's value is optional, you can set the value of the key to
`nil` to keep the key.

```swift
let realm = try! Realm()

// Find the dog we want to update
let wolfie = realm.objects(Dog.self).where {
    $0.name == "Wolfie"
}.first!

// Delete an entry
try! realm.write {
    // Use removeObject(for:)
    wolfie.favoriteParksByCity.removeObject(for: "New York")
    // Or assign `nil` to delete non-optional values.
    // If the value type were optional (e.g. Map<String, String?>)
    // this would assign `nil` to that entry rather than deleting it.
    wolfie.favoriteParksByCity["New York"] = nil
}
XCTAssertNil(wolfie.favoriteParksByCity["New York"])

```

### Delete MutableSet Elements
You can delete specific elements from a `MutableSet`, or clear all of the elements from the set.
If you are working with multiple sets, you can also remove elements in one
set from the other set; see: Update a MutableSet Property.

```swift
let realm = try! Realm()

// Record a dog's name and list of cities he has visited.
let dog = Dog()
dog.name = "Maui"
let dogCitiesVisited = ["New York", "Boston", "Toronto"]
try! realm.write {
    realm.add(dog)
    dog.citiesVisited.insert(objectsIn: dogCitiesVisited)
}
XCTAssertEqual(dog.citiesVisited.count, 3)

// Later... we decide the dog didn't really visit Toronto
// since the plane just stopped there for a layover.
// Remove the element from the set.
try! realm.write {
    dog.citiesVisited.remove("Toronto")
}
XCTAssertEqual(dog.citiesVisited.count, 2)

// Or, in the case where the person entered the data for
// the wrong dog, remove all elements from the set.
try! realm.write {
    dog.citiesVisited.removeAll()
}
XCTAssertEqual(dog.citiesVisited.count, 0)

```

### Delete the Value of an AnyRealmValue
To delete the value of an AnyRealmValue, set it to `.none`.

```swift
let realm = try! Realm()

// Wolfie's companion is "Fluffy the Cat", represented by a string.
// Fluffy has gone to visit friends for the summer, so Wolfie has no companion.
let wolfie = realm.objects(Dog.self).where {
    $0.name == "Wolfie"
}.first!

try! realm.write {
    // You cannot set an AnyRealmValue to nil; you must set it to `.none`, instead.
    wolfie.companion = .none
}

```

## Delete an Object Asynchronously
You can use Swift concurrency features to asynchronously delete objects
using an actor-isolated realm.

This function from the example `RealmActor` defined on the
Use Realm with Actors page shows how you might
delete an object in an actor-isolated realm:

```swift
func deleteTodo(id: ObjectId) async throws {
    try await realm.asyncWrite {
        let todoToDelete = realm.object(ofType: Todo.self, forPrimaryKey: id)
        realm.delete(todoToDelete!)
    }
}

```

And you might perform this deletion using Swift's async syntax:

```swift
let actor = try await RealmActor()
let todoId = await actor.getObjectId(forTodoNamed: "Keep Mr. Frodo safe from that Gollum")

try await actor.deleteTodo(id: todoId)
let updatedTodoCount = await actor.count
if updatedTodoCount == todoCount - 1 {
    print("Successfully deleted the todo")
}

```

This operation does not block or perform I/O on the calling thread. For
more information about writing to realm using Swift concurrency features,
refer to Use Realm with Actors.

---

### Guides Crud Filter Data (`docs/guides/crud/filter-data.md`)

# Filter Data - Swift SDK
## Overview
To filter data in your realm, you can leverage
Realm's query engine.

> Version added: 10.19.0
>

The Realm Swift Query API offers an
idiomatic way for Swift developers to query data. Use Swift-style syntax
to query a realm with the benefits of auto-completion and
type safety. The Realm Swift Query API does not replace the NSPredicate
Query API in newer SDK versions; instead, you can use either.

For SDK versions prior to 10.19.0, or for Objective-C developers,
Realm's query engine supports NSPredicate Query.

## About the Examples on This Page
The examples in this page use a simple data set for a
task list app. The two Realm object types are `Project`
and `Task`. A `Task` has a name, assignee's name, and
completed flag. There is also an arbitrary number for
priority -- higher is more important -- and a count of
minutes spent working on it. Finally, a `Task` can have one
or more string `labels` and one or more integer `ratings`.

A `Project` has zero or more `Tasks`.

See the schema for these two classes, `Project` and
`Task`, below:

#### Objective-C

```objectivec
// Task.h
@interface Task : RLMObject
@property NSString *name;
@property bool isComplete;
@property NSString *assignee;
@property int priority;
@property int progressMinutes;
@end
RLM_COLLECTION_TYPE(Task)
// Task.m
@implementation Task
@end

// Project.h
@interface Project : RLMObject
@property NSString *name;
@property RLMArray<Task> *tasks;
@end
// Project.m
@implementation Project
@end

```

#### Swift

```swift
class Task: Object {
    @Persisted var name = ""
    @Persisted var isComplete = false
    @Persisted var assignee: String?
    @Persisted var priority = 0
    @Persisted var progressMinutes = 0
    @Persisted var labels: MutableSet<String>
    @Persisted var ratings: MutableSet<Int>
}

class Project: Object {
    @Persisted var name = ""
    @Persisted var tasks: List<Task>
}

```

You can set up the realm for these examples with the following code:

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^() {
    // Add projects and tasks here
}];

RLMResults *tasks = [Task allObjectsInRealm:realm];
RLMResults *projects = [Project allObjectsInRealm:realm];

```

#### Swift

```swift
let realm = try! Realm()
try! realm.write {
    // Add tasks and projects here.
    let project = Project()
    project.name = "New Project"
    let task = Task()
    task.assignee = "Alex"
    task.priority = 5
    project.tasks.append(task)
    realm.add(project)
    // ...
}
let tasks = realm.objects(Task.self)
let projects = realm.objects(Project.self)

```

## Realm Swift Query API
> Version added: 10.19.0
> For SDK versions older than 10.19.0, use the NSPredicate query API.
>

You can build a filter with Swift-style syntax using the `.where`
`Realm Swift query API`:

```swift
let realmSwiftQuery = projects.where {
    ($0.tasks.progressMinutes > 1) && ($0.tasks.assignee == "Ali")
}

```

This query API constructs an NSPredicate
to perform the query. It gives developers a type-safe idiomatic API to
use directly, and abstracts away the NSPredicate construction.

The `.where` API takes a callback that evaluates to true or false. The
callback receives an instance of the type being queried, and you can
leverage the compiler to statically check that you are creating valid queries
that reference valid properties.

In the examples on this page, we use the `$0` shorthand to reference
the variable passed into the callback.

### Operators
There are several types of operators available to query a
Realm collection. Queries
work by **evaluating** an operator expression for every
object in the collection being
queried. If the expression resolves to `true`, Realm
Database includes the object in the results collection.

#### Comparison Operators
You can use Swift comparison operators with the Realm Swift
Query API (`==`, `!=`, `>`, `>=`, `<`, `<=`).

> Example:
> The following example uses the query engine's
comparison operators to:
>
> - Find high priority tasks by comparing the value of the `priority` property value with a threshold number, above which priority can be considered high.
> - Find long-running tasks by seeing if the `progressMinutes` property is at or above a certain value.
> - Find unassigned tasks by finding tasks where the `assignee` property is equal to `null`.
>
> ```swift
> let highPriorityTasks = tasks.where {
>     $0.priority > 5
> }
> print("High-priority tasks: \(highPriorityTasks.count)")
>
> let longRunningTasks = tasks.where {
>     $0.progressMinutes >= 120
> }
> print("Long running tasks: \(longRunningTasks.count)")
>
> let unassignedTasks = tasks.where {
>     $0.assignee == nil
> }
> print("Unassigned tasks: \(unassignedTasks.count)")
>
> ```
>

#### Collections
You can query for values within a collection using the `.contains` operators.
You can search for individual values by element, or search within a range.

|Operator|Description|
| --- | --- |
|.in(_ collection:)|Evaluates to `true` if the property referenced by the expression contains an element in the given array.|
|.contains(_ element:)|Equivalent to the `IN` operator. Evaluates to `true` if the property referenced by the expression contains the value.|
|`.contains(_ range:)`|Equivalent to the `BETWEEN` operator. Evaluates to `true` if the property referenced by the expression contains a value that is within the range.|
|`.containsAny(in: )`|Equivalent to the `IN` operator combined with the `ANY` operator. Evaluates to `true` if any elements contained in the given array are present in the collection.|

> Example:
> - Find tasks where the `labels` MutableSet collection property contains "quick win".
> - Find tasks where the `progressMinutes` property is within a given range of minutes.
>
> ```swift
> let quickWinTasks = tasks.where {
>     $0.labels.contains("quick win")
> }
> print("Tasks labeled 'quick win': \(quickWinTasks.count)")
>
> let progressBetween30and60 = tasks.where {
>     $0.progressMinutes.contains(30...60)
> }
> print("Tasks with progress between 30 and 60 minutes: \(progressBetween30and60.count)")
>
> ```
>
> Find tasks where the `labels` MutableSet collection property contains any of the elements in the given array: "quick win" or "bug".
>
> ```swift
> let quickWinOrBugTasks = tasks.where {
>     $0.labels.containsAny(in: ["quick win", "bug"])
> }
> print("Tasks labeled 'quick win' or 'bug': \(quickWinOrBugTasks.count)")
>
> ```
>

> Version added: 10.23.0
> :The `IN` operator
>

The Realm Swift Query API now supports the `IN` operator. Evaluates to `true` if the property referenced by the expression contains the value.

> Example:
> Find tasks assigned to specific teammates Ali or Jamie by seeing if the `assignee` property is in a list of names.
>
> ```swift
> let taskAssigneeInAliOrJamie = tasks.where {
>     let assigneeNames = ["Ali", "Jamie"]
>     return $0.assignee.in(assigneeNames)
> }
> print("Tasks IN Ali or Jamie: \(taskAssigneeInAliOrJamie.count)")
>
> ```
>

#### Logical Operators
You can make compound queries using Swift logical operators (`&&`, `!`,
`||`).

> Example:
> We can use the query language's logical operators to find
all of Ali's completed tasks. That is, we find all tasks
where the `assignee` property value is equal to 'Ali' AND
the `isComplete` property value is `true`:
>
> ```swift
> let aliComplete = tasks.where {
>     ($0.assignee == "Ali") && ($0.isComplete == true)
> }
> print("Ali's complete tasks: \(aliComplete.count)")
>
> ```
>

#### String Operators
You can compare string values using these string operators.
Regex-like wildcards allow more flexibility in search.

> Note:
> You can use the following options with string operators:
>
> - `.caseInsensitive` for case insensitivity. `$0.name.contains("f", options: .caseInsensitive)`
> - `.diacriticInsensitive` for diacritic insensitivity: Realm treats
special characters as the base character (e.g. `é` -> `e`). `$0.name.contains("e", options: .diacriticInsensitive)`
>

|Operator|Description|
| --- | --- |
|.starts(with value: String)|Evaluates to `true` if the collection contains an element whose value begins with the specified string value.|
|.contains(_ value: String)|Evaluates to `true` if the left-hand string expression is found anywhere in the right-hand string expression.|
|.ends(with value: String)|Evaluates to `true` if the collection contains an element whose value ends with the specified string value.|
|.like(_ value: String)|Evaluates to `true` if the left-hand string expression matches the right-hand string wildcard string expression. A wildcard string expression is a string that uses normal characters with two special wildcard characters: The `*` wildcard matches zero or more of any character The `?` wildcard matches any character. For example, the wildcard string "d?g" matches "dog", "dig", and "dug", but not "ding", "dg", or "a dog".|
|==|Evaluates to `true` if the left-hand string is lexicographically equal to the right-hand string.|
|!=|Evaluates to `true` if the left-hand string is not lexicographically equal to the right-hand string.|

> Example:
> The following example uses the query engine's string operators to find:
>
> - Projects with a name starting with the letter 'e'
> - Projects with names that contain 'ie'
> - Projects with an `assignee` property whose value is similar to `Al?x`
> - Projects that contain e-like characters with diacritic insensitivity
>
> ```swift
> // Use the .caseInsensitive option for case-insensitivity.
> let startWithE = projects.where {
>     $0.name.starts(with: "e", options: .caseInsensitive)
> }
> print("Projects that start with 'e': \(startWithE.count)")
>
> let containIe = projects.where {
>     $0.name.contains("ie")
> }
> print("Projects that contain 'ie': \(containIe.count)")
>
> let likeWildcard = tasks.where {
>     $0.assignee.like("Al?x")
> }
> print("Tasks with assignees like Al?x: \(likeWildcard.count)")
>
> // Use the .diacriticInsensitive option for diacritic insensitivity: contains 'e', 'E', 'é', etc.
> let containElike = projects.where {
>     $0.name.contains("e", options: .diacriticInsensitive)
> }
> print("Projects that contain 'e', 'E', 'é', etc.: \(containElike.count)")
>
> ```
>

> Note:
> String sorting and case-insensitive queries are only supported for
character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended
A', and 'Latin Extended B' (UTF-8 range 0-591).
>

#### Geospatial Operators
> Version added: 10.47.0

Use the `geoWithin` operator to query geospatial data with one of the
SDK's provided shapes:

- `GeoCircle`
- `GeoBox`
- `GeoPolygon`

This operator evaluates to `true` if:

- An object has a geospatial data "shape" containing a `String` property
with the value of Point and a `List` containing a longitude/latitude
pair.
- The longitude/latitude of the persisted object falls within the geospatial
query shape.

```swift
let companiesInSmallCircle = realm.objects(Geospatial_Company.self).where {
    $0.location.geoWithin(smallCircle!)
}
print("Number of companies in small circle: \(companiesInSmallCircle.count)")

```

For more information about querying geospatial data, refer to
Query Geospatial Data.

#### Aggregate Operators
You can apply an aggregate operator to a collection property
of a Realm object. Aggregate operators traverse a
collection and reduce it
to a single value.

|Operator|Description|
| --- | --- |
|.avg|Evaluates to the average value of a given numerical property across a collection.|
|.count|Evaluates to the number of objects in the given collection. This is currently only supported on to-many relationship collections and not on lists of primitives. In order to use `.count` on a list of primitives, consider wrapping the primitives in a Realm object.|
|.max|Evaluates to the highest value of a given numerical property across a collection.|
|.min|Evaluates to the lowest value of a given numerical property across a collection.|
|.sum|Evaluates to the sum of a given numerical property across a collection.|

> Example:
> We create a couple of filters to show different facets of
the data:
>
> - Projects with average tasks priority above 5.
> - Projects that contain only low-priority tasks below 5.
> - Projects where all tasks are high-priority above 5.
> - Projects that contain more than 5 tasks.
> - Long running projects.
>
> ```swift
> let averageTaskPriorityAbove5 = projects.where {
>     $0.tasks.priority.avg > 5
> }
> print("Projects with average task priority above 5: \(averageTaskPriorityAbove5.count)")
>
> let allTasksLowerPriority = projects.where {
>     $0.tasks.priority.max < 5
> }
> print("Projects where all tasks are lower priority: \(allTasksLowerPriority.count)")
>
> let allTasksHighPriority = projects.where {
>     $0.tasks.priority.min > 5
> }
> print("Projects where all tasks are high priority: \(allTasksHighPriority.count)")
>
> let moreThan5Tasks = projects.where {
>     $0.tasks.count > 5
> }
> print("Projects with more than 5 tasks: \(moreThan5Tasks.count)")
>
> let longRunningProjects = projects.where {
>     $0.tasks.progressMinutes.sum > 100
> }
> print("Long running projects: \(longRunningProjects.count)")
>
> ```
>

#### Set Operators
A **set operator** uses specific rules to determine whether
to pass each input collection object to the output
collection by applying a given query expression to every element of
a given list property of
the object.

> Example:
> Running the following queries in `projects` collections returns:
>
> - Projects where a set of string `labels` contains any of "quick win", "bug".
> - Projects where any element in a set of integer `ratings` is greater than 3.
>
> ```swift
> let projectsWithGivenLabels = projects.where {
>     $0.tasks.labels.containsAny(in: ["quick win", "bug"])
> }
> print("Projects with quick wins: \(projectsWithGivenLabels.count)")
>
> let projectsWithRatingsOver3 = projects.where {
>     $0.tasks.ratings > 3
> }
> print("Projects with any ratings over 3: \(projectsWithRatingsOver3.count)")
>
> ```
>

### Subqueries
You can iterate through a collection property with another query using a
subquery. To form a subquery, you must wrap the expression in parentheses
and immediately follow it with the `.count` aggregator.

```swift
(<query>).count > n
```

If the expression does not produce a valid subquery, you'll get an
exception at runtime.

> Example:
> Running the following query on a `projects` collection returns projects
with tasks that have not been completed by a user named Alex.
>
> ```swift
> let subquery = projects.where {
>             ($0.tasks.isComplete == false && $0.tasks.assignee == "Alex").count > 0
> }
> print("Projects with incomplete tasks assigned to Alex: \(subquery.count)")
>
> ```
>

## NSPredicate Queries
You can build a filter with NSPredicate:

#### Objective-C

```objectivec
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"progressMinutes > %@ AND name == %@", @1, @"Ali"];

```

#### Swift

```swift
let predicate = NSPredicate(format: "progressMinutes > 1 AND name == %@", "Ali")

```

### Expressions
Filters consist of **expressions** in an NSPredicate. An expression consists of
one of the following:

- The name (keypath) of a property of the object currently being evaluated.
- An operator and up to two argument expression(s).
- A value, such as a string (`'hello'`) or a number (`5`).

### Dot Notation
When referring to an object property, you can use **dot notation** to refer
to child properties of that object. You can even refer to the properties of
embedded objects and relationships with dot notation.

For example, consider a query on an object with a `workplace` property that
refers to a Workplace object. The Workplace object has an embedded object
property, `address`. You can chain dot notations to refer to the zipcode
property of that address:

```objective-c
workplace.address.zipcode == 10012
```

### Substitutions
You can use the following substitutions in your predicate format strings:

- `%@` to specify values
- `%K` to specify [keypaths](https://docs.swift.org/swift-book/ReferenceManual/Expressions.html#grammar_key-path-expression)

#### Objective-C

```objectivec
[NSPredicate predicateWithFormat:@"%K > %@ AND %K == %@", @"progressMinutes", @1, @"name", @"Ali"];

```

#### Swift

```swift
NSPredicate(format: "%K > %@ AND %K == %@", "progressMinutes", NSNumber(1), "name", "Ali")

```

### Operators
There are several types of operators available to filter a
Realm collection. Filters
work by **evaluating** an operator expression for every
object in the collection being
filtered. If the expression resolves to `true`, Realm
Database includes the object in the results collection.

#### Comparison Operators
The most straightforward operation in a search is to compare
values.

> Important:
> The type on both sides of the operator must be equivalent. For
example, comparing an ObjectId with string will result in a precondition failure with a
message like:
>
> ```
> "Expected object of type object id for property 'id' on object of type
> 'User', but received: 11223344556677889900aabb (Invalid value)"
> ```
>
> You can compare any numeric type with any other numeric type.
>

|Operator|Description|
| --- | --- |
|`between`|Evaluates to `true` if the left-hand numerical or date expression is between or equal to the right-hand range. For dates, this evaluates to `true` if the left-hand date is within the right-hand date range.|
|== , =|Evaluates to `true` if the left-hand expression is equal to the right-hand expression.|
|>|Evaluates to `true` if the left-hand numerical or date expression is greater than the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is later than the right-hand date.|
|>=|Evaluates to `true` if the left-hand numerical or date expression is greater than or equal to the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is later than or the same as the right-hand date.|
|`in`|Evaluates to `true` if the left-hand expression is in the right-hand list or string.|
|<|Evaluates to `true` if the left-hand numerical or date expression is less than the right-hand numerical or date expression. For dates, this evaluates to `true` if the left-hand date is earlier than the right-hand date.|
|<=|Evaluates to `true` if the left-hand numeric expression is less than or equal to the right-hand numeric expression. For dates, this evaluates to `true` if the left-hand date is earlier than or the same as the right-hand date.|
|!= , <>|Evaluates to `true` if the left-hand expression is not equal to the right-hand expression.|

> Example:
> The following example uses the query engine's
comparison operators to:
>
> - Find high priority tasks by comparing the value of the `priority` property value with a threshold number, above which priority can be considered high.
> - Find long-running tasks by seeing if the `progressMinutes` property is at or above a certain value.
> - Find unassigned tasks by finding tasks where the `assignee` property is equal to `null`.
> - Find tasks assigned to specific teammates Ali or Jamie by seeing if the `assignee` property is in a list of names.
>
> #### Objective-C
>
> ```objectivec
> NSLog(@"High priority tasks: %lu",
>       [[tasks objectsWithPredicate:[NSPredicate predicateWithFormat:@"priority > %@", @5]] count]);
>
> NSLog(@"Short running tasks: %lu",
>       [[tasks objectsWhere:@"progressMinutes between {1, 15}"] count]);
>
> NSLog(@"Unassigned tasks: %lu",
>       [[tasks objectsWhere:@"assignee == nil"] count]);
>
> NSLog(@"Ali or Jamie's tasks: %lu",
>       [[tasks objectsWhere:@"assignee IN {'Ali', 'Jamie'}"] count]);
>
> NSLog(@"Tasks with progress between 30 and 60 minutes: %lu",
>       [[tasks objectsWhere:@"progressMinutes BETWEEN {30, 60}"] count]);
>
>
> ```
>
>
> #### Swift
>
> ```swift
> let highPriorityTasks = tasks.filter("priority > 5")
> print("High priority tasks: \(highPriorityTasks.count)")
>
> let longRunningTasks = tasks.filter("progressMinutes > 120")
> print("Long running tasks: \(longRunningTasks.count)")
>
> let unassignedTasks = tasks.filter("assignee == nil")
> print("Unassigned tasks: \(unassignedTasks.count)")
>
> let aliOrJamiesTasks = tasks.filter("assignee IN {'Ali', 'Jamie'}")
> print("Ali or Jamie's tasks: \(aliOrJamiesTasks.count)")
>
> let progressBetween30and60 = tasks.filter("progressMinutes BETWEEN {30, 60}")
> print("Tasks with progress between 30 and 60 minutes: \(progressBetween30and60.count)")
>
> ```
>
>

#### Logical Operators
You can make compound predicates using logical operators.

|Operator|Description|
| --- | --- |
|and &&|Evaluates to `true` if both left-hand and right-hand expressions are `true`.|
|not !|Negates the result of the given expression.|
|or \\|\\||Evaluates to `true` if either expression returns `true`.|

> Example:
> We can use the query language's logical operators to find
all of Ali's completed tasks. That is, we find all tasks
where the `assignee` property value is equal to 'Ali' AND
the `isComplete` property value is `true`:
>
> #### Objective-C
>
> ```objectivec
> NSLog(@"Ali's complete tasks: %lu",
>   [[tasks objectsWhere:@"assignee == 'Ali' AND isComplete == true"] count]);
>
> ```
>
>
> #### Swift
>
> ```swift
> let aliComplete = tasks.filter("assignee == 'Ali' AND isComplete == true")
> print("Ali's complete tasks: \(aliComplete.count)")
>
> ```
>
>

#### String Operators
You can compare string values using these string operators.
Regex-like wildcards allow more flexibility in search.

> Note:
> You can use the following modifiers with the string operators:
>
> - `[c]` for case insensitivity. `[NSPredicate predicateWithFormat: @"name CONTAINS[c] 'f'"]``NSPredicate(format: "name CONTAINS[c] 'f'")`
> - `[d]` for diacritic insensitivity: Realm treats special characters as the base character (e.g. `é` -> `e`). `[NSPredicate predicateWithFormat: @"name CONTAINS[d] 'e'"]``NSPredicate(format: "name CONTAINS[d] 'e'")`
>

|Operator|Description|
| --- | --- |
|beginsWith|Evaluates to `true` if the left-hand string expression begins with the right-hand string expression. This is similar to `contains`, but only matches if the right-hand string expression is found at the beginning of the left-hand string expression.|
|contains , in|Evaluates to `true` if the left-hand string expression is found anywhere in the right-hand string expression.|
|endsWith|Evaluates to `true` if the left-hand string expression ends with the right-hand string expression. This is similar to `contains`, but only matches if the left-hand string expression is found at the very end of the right-hand string expression.|
|like|Evaluates to `true` if the left-hand string expression matches the right-hand string wildcard string expression. A wildcard string expression is a string that uses normal characters with two special wildcard characters: The `*` wildcard matches zero or more of any character The `?` wildcard matches any character. For example, the wildcard string "d?g" matches "dog", "dig", and "dug", but not "ding", "dg", or "a dog".|
|== , =|Evaluates to `true` if the left-hand string is lexicographically equal to the right-hand string.|
|!= , <>|Evaluates to `true` if the left-hand string is not lexicographically equal to the right-hand string.|

> Example:
> We use the query engine's string operators to find
projects with a name starting with the letter 'e' and
projects with names that contain 'ie':
>
> #### Objective-C
>
> ```objectivec
> // Use [c] for case-insensitivity.
> NSLog(@"Projects that start with 'e': %lu",
>   [[projects objectsWhere:@"name BEGINSWITH[c] 'e'"] count]);
>
> NSLog(@"Projects that contain 'ie': %lu",
>   [[projects objectsWhere:@"name CONTAINS 'ie'"] count]);
>
> ```
>
>
> #### Swift
>
> ```swift
> // Use [c] for case-insensitivity.
> let startWithE = projects.filter("name BEGINSWITH[c] 'e'")
> print("Projects that start with 'e': \(startWithE.count)")
>
> let containIe = projects.filter("name CONTAINS 'ie'")
> print("Projects that contain 'ie': \(containIe.count)")
>
> // [d] for diacritic insensitivty: contains 'e', 'E', 'é', etc.
> let containElike = projects.filter("name CONTAINS[cd] 'e'")
> print("Projects that contain 'e', 'E', 'é', etc.: \(containElike.count)")
>
> ```
>
>

> Note:
> String sorting and case-insensitive queries are only supported for
character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended
A', and 'Latin Extended B' (UTF-8 range 0-591).
>

#### Geospatial Operators
> Version added: 10.47.0

You can perform a geospatial query using the `IN` operator with one
of the SDK's provided shapes:

- `GeoCircle`
- `GeoBox`
- `GeoPolygon`

This operator evaluates to `true` if:

- An object has a geospatial data "shape" containing a `String` property
with the value of Point and a `List` containing a longitude/latitude
pair.
- The longitude/latitude of the persisted object falls within the geospatial
query shape.

```swift
let filterArguments = NSMutableArray()
filterArguments.add(largeBox)
let companiesInLargeBox = realm.objects(Geospatial_Company.self)
    .filter(NSPredicate(format: "location IN %@", argumentArray: filterArguments as? [Any]))
print("Number of companies in large box: \(companiesInLargeBox.count)")

```

For more information about querying geospatial data, refer to
Query Geospatial Data.

#### Aggregate Operators
You can apply an aggregate operator to a collection property
of a Realm object. Aggregate operators traverse a
collection and reduce it
to a single value.

|Operator|Description|
| --- | --- |
|@avg|Evaluates to the average value of a given numerical property across a collection.|
|@count|Evaluates to the number of objects in the given collection. This is currently only supported on to-many relationship collections and not on lists of primitives. In order to use `@count` on a list of primitives, consider wrapping the primitives in a Realm object.|
|@max|Evaluates to the highest value of a given numerical property across a collection.|
|@min|Evaluates to the lowest value of a given numerical property across a collection.|
|@sum|Evaluates to the sum of a given numerical property across a collection.|

> Example:
> We create a couple of filters to show different facets of
the data:
>
> - Projects with average tasks priority above 5.
> - Long running projects.
>
> #### Objective-C
>
> ```objectivec
> NSLog(@"Projects with average tasks priority above 5: %lu",
>       [[projects objectsWhere:@"tasks.@avg.priority > 5"] count]);
>
> NSLog(@"Projects where all tasks are lower priority: %lu",
>       [[projects objectsWhere:@"tasks.@max.priority < 5"] count]);
>
> NSLog(@"Projects where all tasks are high priority: %lu",
>       [[projects objectsWhere:@"tasks.@min.priority > 5"] count]);
>
> NSLog(@"Projects with more than 5 tasks: %lu",
>       [[projects objectsWhere:@"tasks.@count > 5"] count]);
>
> NSLog(@"Long running projects: %lu",
>       [[projects objectsWhere:@"tasks.@sum.progressMinutes > 100"] count]);
>
> ```
>
>
> #### Swift
>
> ```swift
> let averageTaskPriorityAbove5 = projects.filter("tasks.@avg.priority > 5")
> print("Projects with average task priority above 5: \(averageTaskPriorityAbove5.count)")
>
> let allTasksLowerPriority = projects.filter("tasks.@max.priority < 5")
> print("Projects where all tasks are lower priority: \(allTasksLowerPriority.count)")
>
> let allTasksHighPriority = projects.filter("tasks.@min.priority > 5")
> print("Projects where all tasks are high priority: \(allTasksHighPriority.count)")
>
> let moreThan5Tasks = projects.filter("tasks.@count > 5")
> print("Projects with more than 5 tasks: \(moreThan5Tasks.count)")
>
> let longRunningProjects = projects.filter("tasks.@sum.progressMinutes > 100")
> print("Long running projects: \(longRunningProjects.count)")
>
> ```
>
>

#### Set Operators
A **set operator** uses specific rules to determine whether
to pass each input collection object to the output
collection by applying a given predicate to every element of
a given list property of
the object.

|Operator|Description|
| --- | --- |
|`ALL`|Returns objects where the predicate evaluates to `true` for all objects in the collection.|
|`ANY`, `SOME`|Returns objects where the predicate evaluates to `true` for any objects in the collection.|
|`NONE`|Returns objects where the predicate evaluates to false for all objects in the collection.|

> Example:
> We use the query engine's set operators to find:
>
> - Projects with no complete tasks.
> - Projects with any top priority tasks.
>
> #### Objective-C
>
> ```objectivec
> NSLog(@"Projects with no complete tasks: %lu",
>   [[projects objectsWhere:@"NONE tasks.isComplete == true"] count]);
>
> NSLog(@"Projects with any top priority tasks: %lu",
>   [[projects objectsWhere:@"ANY tasks.priority == 10"] count]);
>
> ```
>
>
> #### Swift
>
> ```swift
> let noCompleteTasks = projects.filter("NONE tasks.isComplete == true")
> print("Projects with no complete tasks: \(noCompleteTasks.count)")
>
> let anyTopPriorityTasks = projects.filter("ANY tasks.priority == 10")
> print("Projects with any top priority tasks: \(anyTopPriorityTasks.count)")
>
> ```
>
>

### Subqueries
You can iterate through a collection property with another query using the
`SUBQUERY()` predicate function. `SUBQUERY()` has the following signature:

```objective-c
SUBQUERY(<collection>, <variableName>, <predicate>)
```

- `collection`: the name of the list property to iterate through
- `variableName`: a variable name of the current element to use in the subquery
- `predicate`: a string that contains the subquery predicate. You can use the
variable name specified by `variableName` to refer to the currently iterated
element.

> Example:
> Running the following filter on a `projects` collection returns projects
with tasks that have not been completed by a user named Alex.
>
> #### Objective-C
>
> ```objectivec
> NSPredicate *predicate = [NSPredicate predicateWithFormat:
>                           @"SUBQUERY(tasks, $task, $task.isComplete == %@ AND $task.assignee == %@).@count > 0",
>                           @NO,
>                           @"Alex"];
> NSLog(@"Projects with incomplete tasks assigned to Alex: %lu",
>   [[projects objectsWithPredicate:predicate] count]);
>
> ```
>
>
> #### Swift
>
> ```swift
> let predicate = NSPredicate(
>     format: "SUBQUERY(tasks, $task, $task.isComplete == false AND $task.assignee == %@).@count > 0", "Alex")
> print("Projects with incomplete tasks assigned to Alex: \(projects.filter(predicate).count)")
>
> ```
>
>

---

### Guides Crud React To Changes (`docs/guides/crud/react-to-changes.md`)

# React to Changes - Swift SDK
All Realm objects are **live objects**, which means they
automatically update whenever they're modified. Realm emits a
notification event whenever any property changes. You can register a
notification handler to listen for these notification events, and update
your UI with the latest data.

This page shows how to manually register notification listeners in Swift.
Realm SDK for Swift offers SwiftUI property wrappers to make it easy to
automatically update the UI when data changes. For more about how to use
the SwiftUI property wrappers to react to changes, refer to
Observe an Object.

## Register a Realm Change Listener
You can register a notification handler on an entire realm. Realm calls the notification
handler whenever any write transaction involving that Realm is
committed. The handler receives no information about the change.

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

// Observe realm notifications. Keep a strong reference to the notification token
// or the observation will stop.
RLMNotificationToken *token = [realm addNotificationBlock:^(RLMNotification  _Nonnull notification, RLMRealm * _Nonnull realm) {
    // `notification` is an enum specifying what kind of notification was emitted.
    // ... update UI ...
}];

// ...

// Later, explicitly stop observing.
[token invalidate];

```

#### Swift

```swift
let realm = try! Realm()

// Observe realm notifications. Keep a strong reference to the notification token
// or the observation will stop.
let token = realm.observe { notification, realm in
    // `notification` is an enum specifying what kind of notification was emitted
    viewController.updateUI()
}

// ...

// Later, explicitly stop observing.
token.invalidate()

```

## Register a Collection Change Listener
You can register a notification handler on a collection within a
realm.

Realm notifies your handler:

- After first retrieving the collection.
- Whenever a write transaction adds, changes, or removes objects in the collection.

Notifications describe the changes since the prior notification with
three lists of indices: the indices of the objects that were deleted,
inserted, and modified.

> Important:
> In collection notification handlers, always apply changes
in the following order: deletions, insertions, then
modifications. Handling insertions before deletions may
result in unexpected behavior.
>

Collection notifications provide a `change` parameter that reports which
objects are deleted, added, or modified during the write transaction. This
`RealmCollectionChange`
resolves to an array of index paths that you can pass to a `UITableView`'s
batch update methods.

> Important:
> This example of a collection change listener does not support
high-frequency updates. Under an intense workload, this collection
change listener may cause the app to throw an exception.
>

#### Objective-C

```
/* Detailed source-code truncated for AI context efficiency. */
```

#### Swift

```
/* Detailed source-code truncated for AI context efficiency. */
```

## Register an Object Change Listener
You can register a notification handler on a specific object
within a realm. Realm notifies your handler:

- When the object is deleted.
- When any of the object's properties change.

The handler receives information about what fields changed
and whether the object was deleted.

#### Objective-C

```objectivec
@interface Dog : RLMObject
@property NSString *name;
@property int age;
@end

@implementation Dog
@end

RLMNotificationToken *objectNotificationToken = nil;

void objectNotificationExample() {
    Dog *dog = [[Dog alloc] init];
    dog.name = @"Max";
    dog.age = 3;
    
    // Open the default realm
    RLMRealm *realm = [RLMRealm defaultRealm];
    [realm transactionWithBlock:^{
        [realm addObject:dog];
    }];

    // Observe object notifications. Keep a strong reference to the notification token
    // or the observation will stop. Invalidate the token when done observing.
    objectNotificationToken = [dog addNotificationBlock:^(BOOL deleted, NSArray<RLMPropertyChange *> * _Nullable changes, NSError * _Nullable error) {
        if (error != nil) {
            NSLog(@"An error occurred: %@", [error localizedDescription]);
            return;
        }
        if (deleted) {
            NSLog(@"The object was deleted.");
            return;
        }
        NSLog(@"Property %@ changed to '%@'",
              changes[0].name,
              changes[0].value);
    }];

    // Now update to trigger the notification
    [realm transactionWithBlock:^{
        dog.name = @"Wolfie";
    }];

}

```

#### Swift

```swift
// Define the dog class.
class Dog: Object {
    @Persisted var name = ""
}

var objectNotificationToken: NotificationToken?

func objectNotificationExample() {
    let dog = Dog()
    dog.name = "Max"

    // Open the default realm.
    let realm = try! Realm()
    try! realm.write {
        realm.add(dog)
    }
    // Observe object notifications. Keep a strong reference to the notification token
    // or the observation will stop. Invalidate the token when done observing.
    objectNotificationToken = dog.observe { change in
        switch change {
        case .change(let object, let properties):
            for property in properties {
                print("Property '\(property.name)' of object \(object) changed to '\(property.newValue!)'")
            }
        case .error(let error):
            print("An error occurred: \(error)")
        case .deleted:
            print("The object was deleted.")
        }
    }

    // Now update to trigger the notification
    try! realm.write {
        dog.name = "Wolfie"
    }
}

```

## Register a Key Path Change Listener
> Version added: 10.12.0

In addition to registering a notification handler on an `object`
or `collection`, you can pass an optional string `keyPaths` parameter to specify the key path or
key paths to watch.

> Example:
> ```
/* Detailed source-code truncated for AI context efficiency. */
```
>

> Version added: 10.14.0

You can `observe`
a partially type-erased [PartialKeyPath](https://developer.apple.com/documentation/swift/partialkeypath)
on `Objects` or `RealmCollections`.

```swift
objectNotificationToken = dog.observe(keyPaths: [\Dog.favoriteToy, \Dog.age], { change in
```

When you specify `keyPaths`, *only* changes to those
`keyPaths` trigger notification blocks. Any other changes do not trigger
notification blocks.

> Example:
> Consider a `Dog` object where one of its properties is a list of
`siblings`:
>
> ```swift
> class Dog: Object {
>     @Persisted var name = ""
>     @Persisted var siblings: List<Dog>
>     @Persisted var age: Int?
> }
> ```
>
> If you pass `siblings` as a `keyPath` to observe, any insertion,
deletion, or modification to the `siblings` list would trigger a
notification. However, a change to `someSibling.name` would not trigger
a notification, unless you explicitly observed `["siblings.name"]`.
>

> Note:
> Multiple notification tokens on the same object which filter for
separate key paths *do not* filter exclusively. If one key path
change is satisfied for one notification token, then all notification
token blocks for that object will execute.
>

### Realm Collections
When you observe key paths on the various collection types, expect these
behaviors:

- `LinkingObjects`:
Observing a property of the LinkingObject triggers a notification for a
change to that property, but does not trigger notifications for changes to
its other properties. Insertions or deletions to the list or the object
that the list is on trigger a notification.
- `Lists`:
Observing a property of the list's object will triggers a notification for
a change to that property, but does not trigger notifications for changes
to its other properties. Insertions or deletions to the list or the object
that the list is on trigger a notification.
- `Map`:
Observing a property of the map's object triggers a notification for a change
to that property, but does not trigger notifications for changes to its other
properties. Insertions or deletions to the Map or the object that the map is
on trigger a notification. The `change` parameter reports, in the form of
keys within the map, which key-value pairs are added, removed, or modified
during each write transaction.
- `MutableSet`:
Observing a property of a MutableSet's object triggers a notification
for a change to that property, but does not trigger notifications for changes
to its other properties. Insertions or deletions to the MutableSet or the
object that the MutableSet is on trigger a notification.
- `Results`:
Observing a property of the Result triggers a notification for a change to
that property, but does not trigger notifications for changes to its other
properties. Insertions or deletions to the Result trigger a notification.

## Write Silently
You can write to a realm *without* sending a notification to a
specific observer by passing the observer's notification token in an
array to `realm.write(withoutNotifying:_)`:

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

// Observe realm notifications
RLMNotificationToken *token = [realm addNotificationBlock:^(RLMNotification  _Nonnull notification, RLMRealm * _Nonnull realm) {
    // ... handle update
}];

// Later, pass the token in an array to the realm's `-transactionWithoutNotifying:block:` method.
// Realm will _not_ notify the handler after this write.
[realm transactionWithoutNotifying:@[token] block:^{
   // ... write to realm
}];

// Finally
[token invalidate];

```

#### Swift

```swift
let realm = try! Realm()

// Observe realm notifications
let token = realm.observe { notification, realm in
    // ... handle update
}

// Later, pass the token in an array to the realm.write(withoutNotifying:)
// method to write without sending a notification to that observer.
try! realm.write(withoutNotifying: [token]) {
    // ... write to realm
}

// Finally
token.invalidate()

```

## Stop Watching for Changes
Observation stops when the token returned by an `observe` call becomes
invalid. You can explicitly invalidate a token by calling its
`invalidate()` method.

> Important:
> Notifications stop if the token is in a local variable that goes out
of scope.
>

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

// Observe and obtain token
RLMNotificationToken *token = [realm addNotificationBlock:^(RLMNotification  _Nonnull notification, RLMRealm * _Nonnull realm) {
    /* ... */
}];

// Stop observing
[token invalidate];

```

#### Swift

```swift
let realm = try! Realm()

// Observe and obtain token
let token = realm.observe { notification, realm in /* ... */ }

// Stop observing
token.invalidate()

```

## Key-value Observation
### Key-value Observation Compliance
Realm objects are [key-value observing (KVO)
compliant](https://developer.apple.com/documentation/swift/cocoa_design_patterns/using_key-value_observing_in_swift)
for most properties:

- Almost all managed (non-ignored) properties on `Object` subclasses
- The `invalidated` property on `Object` and `List`

You cannot observe `LinkingObjects` properties via Key-value observation.

> Important:
> You cannot add an object to a realm (with `realm.add(obj)` or similar
methods) while it has any registered observers.
>

### Managed vs. Unmanaged KVO Considerations
Observing the properties of unmanaged instances of `Object` subclasses
works like any other dynamic property.

Observing the properties of managed objects works differently. With
realm-managed objects, the value of a property may change when:

- You assign to it
- The realm is refreshed, either manually with `realm.refresh()` or
automatically on a runloop thread
- You begin a write transaction after changes on another thread

Realm applies changes made in the write transaction(s) on other threads
at once. Observers see Key-value observation notifications at once.
Intermediate steps do not trigger KVO notifications.

> Example:
> Say your app performs a write transaction that increments a property
from 1 to 10. On the main thread, you get a single notification of a
change directly from 1 to 10. You won't get notifications for every
incremental change between 1 and 10.
>

Avoid modifying managed Realm objects from within
`observeValueForKeyPath(_:ofObject:change:context:)`. Property values
can change when not in a write transaction, or as part of beginning a
write transaction.

### Observing Realm Lists
Observing changes made to Realm `List` properties is simpler than
`NSMutableArray` properties:

- You don't have to mark `List` properties as dynamic to observe them.
- You can call modification methods on `List` directly. Anyone observing
the property that stores it gets a notification.

You don't need to use `mutableArrayValueForKey(_:)`, although realm
does support this for code compatibility.

> Seealso:
> Examples of using Realm with [ReactiveCocoa from Objective-C](https://github.com/realm/realm-swift/tree/master/examples/ios/objc/TableView),
and [ReactKit from Swift](https://github.com/realm/realm-swift/tree/v2.3.0/examples/ios/swift-2.2/ReactKit).
>

## React to Changes on a Different Actor
You can observe notifications on a different actor. Calling
`await object.observe(on: Actor)` or
`await collection.observe(on: Actor)` registers a block to be called each
time the object or collection changes.

```
/* Detailed source-code truncated for AI context efficiency. */
```

For more information about change notifications on another actor,
refer to Observe Notifications on a Different Actor.

## React to Changes to a Class Projection
Like other realm objects, you can react to changes
to a class projection. When you register a class projection change listener,
you see notifications for changes made through the class projection object
directly. You also see notifications for changes to the underlying object's
properties that project through the class projection object.

Properties on the underlying object that are not `@Projected` in the
class projection do not generate notifications.

This notification block fires for changes in:

- `Person.firstName` property of the class projection's underlying
`Person` object, but not changes to `Person.lastName` or
`Person.friends`.
- `PersonProjection.firstName` property, but not another class projection
that uses the same underlying object's property.

```swift
let realm = try! Realm()
let projectedPerson = realm.objects(PersonProjection.self).first(where: { $0.firstName == "Jason" })!
let token = projectedPerson.observe(keyPaths: ["firstName"], { change in
    switch change {
    case .change(let object, let properties):
        for property in properties {
            print("Property '\(property.name)' of object \(object) changed to '\(property.newValue!)'")
        }
    case .error(let error):
        print("An error occurred: \(error)")
    case .deleted:
        print("The object was deleted.")
    }
})

// Now update to trigger the notification
try! realm.write {
    projectedPerson.firstName = "David"
}

```

## Notification Delivery
Notification delivery can vary depending on:

- Whether or not the notification occurs within a write transaction
- The relative threads of the write and the observation

When your application relies on the timing of notification delivery, such
as when you use notifications to update a `UITableView`, it's important
to understand the specific behaviors for your application code's context.

### Perform Writes Only on a Different Thread than the Observing Thread
Reading an observed collection or object from inside a change notification
always accurately tells you what has changed in the collection passed to
the callback since the last time the callback was invoked.

Reading collections or objects outside of change notifications always gives
you the exact same values you saw in the most recent change notification
for that object.

Reading objects other than the observed one *inside* a change notification
may see a different value prior to the notification for that change being
delivered. Realm `refresh` brings the entire realm from 'old version' to
'latest version' in one operation. However, there might have been multiple
change notifications fired between 'old version' and 'latest version'. Inside
a callback, you may see changes that have pending notifications.

Writes on different threads eventually become visible on the observing
thread. Explicitly calling `refresh()` blocks until the writes made on
other threads are visible and the appropriate notifications have been sent.
If you call `refresh()` within a notification callback, it's a no-op.

### Perform Writes on the Observing Thread, Outside of Notifications
At the start of the write transaction all behaviors above apply to this
context. Additionally, you can expect to always see the latest version of
the data.

Inside a write transaction, the only changes you see are those you've made
so far within the write transaction.

Between committing a write transaction and the next set of change
notifications being sent, you can see the changes you made in the write
transaction, but no other changes. Writes made on different threads do
not become visible until you receive the next set of notifications.
Performing another write on the same thread sends notifications for the
previous write first.

### Perform Writes Inside of Notifications
When you perform writes within notifications, you see many of the same
behaviors above, with a few exceptions.

Callbacks invoked before the one that performed a write behave normally.
While Realm invokes change callbacks in a stable order, this is not strictly
the order in which you added the observations.

If beginning the write refreshes the realm, which can happen if another
thread is making writes, this triggers recursive notifications. These
nested notifications report the changes made since the last call to the
callback. For callbacks before the one making the write, this means the
inner notification reports only the changes made after the ones already
reported in the outer notification. If the callback making the write tries
to write again in the inner notification, Realm throws an exception.
The callbacks after the one making the write get a single notification for
both sets of changes.

After the callback completes the write and returns, Realm does not invoke
any of the subsequent callbacks as they no longer have any changes to report.
Realm provides a notification later for the write as if the write had happened
outside of a notification.

If beginning the write doesn't refresh the realm, the write happens as
usual. However, Realm invokes the subsequent callbacks in an inconsistent
state. They continue to report the original change information, but the
observed object/collection now includes the changes from the write made
in the previous callback.

If you try to perform manual checks and write handling to get more fine-grained
notifications from within a write transaction, you can get notifications
nested more than two levels deep. An example of a manual write handling is
checking `realm.isInWriteTransaction`, and if so making changes, calling
`realm.commitWrite()` and then `realm.beginWrite()`. The nested
notifications and potential for error make this manual manipulation
error-prone and difficult to debug.

You can use the writeAsync API to sidestep complexity
if you don't need fine-grained change information from inside your write block.
Observing an async write similar to this provides notifications even if the
notification happens to be delivered inside a write transaction:

```swift
let token = dog.observe(keyPaths: [\Dog.age]) { change in
   guard case let .change(dog, _) = change else { return }
   dog.realm!.writeAsync {
      dog.isPuppy = dog.age < 2
   }
}
```

However, because the write is async the realm may have changed between the
notification and when the write happens. In this case, the change information
passed to the notification may no longer be applicable.

### Updating a UITableView Based on Notifications
If you only update a `UITableView` via notifications, in the time between
a write transaction and the next notification arriving, the TableView's
state is out of sync with the data. The TableView could have a pending update
scheduled, which can appear to cause delayed or inconsistent updates.

You can address these behaviors in a few ways.

The following examples use this very basic `UITableViewController`.

```
/* Detailed source-code truncated for AI context efficiency. */
```

#### Update the UITableView Directly Without a Notification
Updating the `UITableView` directly without waiting for a notification
provides the most responsive UI. This code updates the TableView immediately
instead of requiring hops between threads, which add a small amount of
lag to each update. The downside is that it requires frequent manual
updates to the view.

```swift
func delete(at index: Int) throws {
    try realm.write(withoutNotifying: [notificationToken]) {
        realm.delete(results[index])
    }
    tableView.deleteRows(at: [IndexPath(row: index, section: 0)], with: .automatic)
}

```

#### Force a Refresh After a Write
Forcing a `refresh()` after a write provides the notifications from the
write immediately rather than on a future run of the run loop. There's no
window for the TableView to read out-of-sync values.

The downside is that this means things we recommend doing in the background,
such as writing, rerunning the query and re-sorting the results, happen
on the main thread. When these operations are computationally expensive,
this can cause delays on the main thread.

```swift
func delete(at index: Int) throws {
    try realm.write {
        realm.delete(results[index])
    }
    realm.refresh()
}

```

#### Perform the Write on a Background Thread
Performing a write on a background thread blocks the main thread for the
least amount of time. However, the code to perform a write on the background
requires more familiarity with Realm's threading model and Swift DispatchQueue
usage. Since the write doesn't happen on the main thread, the main thread
never sees the write before the notifications arrive.

```swift
func delete(at index: Int) throws {
    func delete(at index: Int) throws {
        @ThreadSafe var object = results[index]
        DispatchQueue.global().async {
            guard let object = object else { return }
            let realm = object.realm!
            try! realm.write {
                if !object.isInvalidated {
                    realm.delete(object)
                }
            }
        }
    }
}

```

## Change Notification Limits
Changes in nested documents deeper than four levels down do not trigger
change notifications.

If you have a data structure where you need to listen for changes five
levels down or deeper, workarounds include:

- Refactor the schema to reduce nesting.
- Add something like "push-to-refresh" to enable users to manually refresh data.

In the Swift SDK, you can also use
key path filtering to work
around this limitation. This feature is not available in the other SDKs.

---

### Guides Crud Read (`docs/guides/crud/read.md`)

# CRUD - Read - Swift SDK
## Read from a Realm
A read from a realm generally consists of the following
steps:

- Get all objects of a certain type from the realm.
- Optionally, filter the results.
- Optionally, sort the results.
- Alternately, get all objects of a certain type, divided into
sections. As with regular results, you can
filter and sort sectioned results.

Query, filter, and sort operations return either a results or
SectionedResults collection. These
collections are live, meaning they always contain the latest
results of the associated query.

### Read Characteristics
When you design your app's data access patterns around the
following three key characteristics of reads in Realm,
you can be confident you are reading data as
efficiently as possible.

#### Results Are Not Copies
Results to a query are not copies of your data: modifying
the results of a query will modify the data on disk
directly. This memory mapping also means that results are
**live**: that is, they always reflect the current state on
disk.

See also: Collections are Live.

#### Results Are Lazy
Realm only runs a query when you actually request the
results of that query. This lazy evaluation enables you to write
elegant, highly performant code for handling large data sets and complex
queries. You can chain several filter and sort operations without requiring extra work to process the
intermediate state.

#### References Are Retained
One benefit of Realm's object model is that
Realm automatically retains all of an object's
relationships as direct
references, so you can traverse your graph of relationships
directly through the results of a query.

A **direct reference**, or pointer, allows you to access a
related object's properties directly through the reference.

Other databases typically copy objects from database storage
into application memory when you need to work with them
directly. Because application objects contain direct
references, you are left with a choice: copy the object
referred to by each direct reference out of the database in
case it's needed, or just copy the foreign key for each
object and query for the object with that key if it's
accessed. If you choose to copy referenced objects into
application memory, you can use up a lot of resources for
objects that are never accessed, but if you choose to only
copy the foreign key, referenced object lookups can cause
your application to slow down.

Realm bypasses all of this using zero-copy
live objects. Realm object accessors point
directly into database storage using memory mapping, so there is no
distinction between the objects in Realm and the results
of your query in application memory. Because of this, you can traverse
direct references across an entire realm from any query result.

### Limiting Query Results
As a result of lazy evaluation, you do not need any special mechanism to
limit query results with Realm. For example, if your query
matches thousands of objects, but you only want to load the first ten,
simply access only the first ten elements of the results collection.

### Pagination
Thanks to lazy evaluation, the common task of pagination becomes quite
simple. For example, suppose you have a results collection associated
with a query that matches thousands of objects in your realm. You
display one hundred objects per page. To advance to any page, simply
access the elements of the results collection starting at the index that
corresponds to the target page.

## Read Realm Objects
### About The Examples On This Page
The examples on this page use the following models:

#### Objective-C

```objectivec
// DogToy.h
@interface DogToy : RLMObject
@property NSString *name;
@end

// Dog.h
@interface Dog : RLMObject
@property NSString *name;
@property int age;
@property NSString *color;

// To-one relationship
@property DogToy *favoriteToy;

@end

// Enable Dog for use in RLMArray
RLM_COLLECTION_TYPE(Dog)

// Person.h
// A person has a primary key ID, a collection of dogs, and can be a member of multiple clubs.
@interface Person : RLMObject
@property int _id;
@property NSString *name;

// To-many relationship - a person can have many dogs
@property RLMArray<Dog *><Dog> *dogs;

// Inverse relationship - a person can be a member of many clubs
@property (readonly) RLMLinkingObjects *clubs;
@end

RLM_COLLECTION_TYPE(Person)

// DogClub.h
@interface DogClub : RLMObject
@property NSString *name;
@property RLMArray<Person *><Person> *members;
@end

// Dog.m
@implementation Dog
@end

// DogToy.m
@implementation DogToy
@end

// Person.m
@implementation Person
// Define the primary key for the class
+ (NSString *)primaryKey {
    return @"_id";
}

// Define the inverse relationship to dog clubs
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"clubs": [RLMPropertyDescriptor descriptorWithClass:DogClub.class propertyName:@"members"],
    };
}
@end

// DogClub.m
@implementation DogClub
@end

```

#### Swift

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Find a Specific Object by Primary Key
#### Objective-C

If you know the primary key for
a given object, you can look it up directly with
`+[RLMObject objectForPrimaryKey:]`.

```objectivec
// Get a specific person from the default realm
Person *specificPerson = [Person objectForPrimaryKey:@12345];

```

#### Swift

If you know the primary key for a given
object, you can look it up directly with
`Realm.object(ofType:forPrimaryKey:)`.

```swift
let realm = try! Realm()

let specificPerson = realm.object(ofType: Person.self, forPrimaryKey: 12345)

```

### Query All Objects of a Given Type
#### Objective-C

To query for objects of a given type in a realm, pass the realm
instance to `+[YourRealmObjectClass allObjectsInRealm:]`.
Replace `YourRealmObjectClass` with your Realm object class
name. This returns an `RLMResults` object representing all objects of the
given type in the realm.

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

RLMResults *dogs = [Dog allObjectsInRealm:realm];
RLMResults *people = [Person allObjectsInRealm:realm];

```

#### Swift

To query for objects of a given type in a realm, pass the metatype
instance `YourClassName.self` to `Realm.objects(_)`.
This returns a `Results` object
representing all objects of the given type in the realm.

```swift
let realm = try! Realm()
// Access all dogs in the realm
let dogs = realm.objects(Dog.self)

```

### Filter Queries Based on Object Properties
A filter selects a subset of results based on the value(s) of one or
more object properties. Realm provides a full-featured
query engine that you can use to define filters.

#### Swift

> Version added: 10.19.0

To use the Realm Swift Query API,
call `.where` with a closure that
contains a query expression as an argument.

```swift
let realm = try! Realm()
// Access all dogs in the realm
let dogs = realm.objects(Dog.self)

// Query by age
let puppies = dogs.where {
    $0.age < 2
}

// Query by person
let dogsWithoutFavoriteToy = dogs.where {
    $0.favoriteToy == nil
}

// Query by person's name
let dogsWhoLikeTennisBalls = dogs.where {
    $0.favoriteToy.name == "Tennis ball"
}

```

#### Swift Nspredicate

To filter, call `Results.filter(_:)`
with a query predicate.

```swift
let realm = try! Realm()
// Access all dogs in the realm
let dogs = realm.objects(Dog.self)

// Filter by age
let puppies = dogs.filter("age < 2")

// Filter by person
let dogsWithoutFavoriteToy = dogs.filter("favoriteToy == nil")

// Filter by person's name
let dogsWhoLikeTennisBalls = dogs.filter("favoriteToy.name == 'Tennis ball'")

```

#### Objective-C

To filter, call `-[RLMResults objectsWhere:]`
with a query predicate.

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

// Access all dogs in the realm
RLMResults *dogs = [Dog allObjectsInRealm:realm];

// Filter by age
RLMResults *puppies = [dogs objectsWhere:@"age < 2"];

// Filter by favorite toy
RLMResults *dogsWithoutFavoriteToy = [dogs objectsWhere:@"favoriteToy == nil"];

// Filter by favorite toy's name
RLMResults *dogsWhoLikeTennisBalls = [dogs objectsWhere:@"favoriteToy.name == %@", @"Tennis ball"];

```

> Tip:
> To filter a query based on a property of an embedded object or a related object, use dot-notation as if it were
in a regular, nested object.
>

### Filter on Object ID Properties
The types in your predicate must match the types of the
properties. Avoid comparing
`ObjectId` properties to strings, as
Realm does not automatically convert strings to ObjectIds.

#### Swift

> Version added: 10.19.0

The Realm Swift Query API's built-in type safety simplifies writing a
query with an ObjectId:

```swift
let realm = try! Realm()

let dogToys = realm.objects(DogToy.self)

// Get specific user by ObjectId id
let specificToy = dogToys.where {
    $0.id == ObjectId("11223344556677889900aabb")
}

```

#### Swift Nspredicate

The following example shows the correct and incorrect way to write a
query with an ObjectId given the following Realm object:

```swift
let realm = try! Realm()

let dogToys = realm.objects(DogToy.self)

// Get specific toy by ObjectId id
let specificToy = dogToys.filter("id = %@", ObjectId("11223344556677889900aabb")).first

// WRONG: Realm will not convert the string to an object id
// users.filter("id = '11223344556677889900aabb'") // not ok
// users.filter("id = %@", "11223344556677889900aabb") // not ok

```

### Query a Relationship
You can query through a relationship the same way you would access a
member of a regular Swift or Objective-C object.

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

// Establish a relationship
Dog *dog = [[Dog alloc] init];
dog.name = @"Rex";
dog.age = 10;

Person *person = [[Person alloc] init];
person._id = 12345;
[person.dogs addObject:dog];

[realm transactionWithBlock:^() {
    [realm addObject:person];
}];

// Later, query the specific person
Person *specificPerson = [Person objectForPrimaryKey:@12345];

// Access directly through a relationship
NSLog(@"# dogs: %lu", [specificPerson.dogs count]);
NSLog(@"First dog's name: %@", specificPerson.dogs[0].name);

```

#### Swift

```swift
let realm = try! Realm()

// Establish a relationship
let dog = Dog()
dog.name = "Rex"
dog.age = 10

let person = Person()
person.id = 12345
person.dogs.append(dog)

try! realm.write {
    realm.add(person)
}

// Later, query the specific person
let specificPerson = realm.object(ofType: Person.self, forPrimaryKey: 12345)

// Access directly through a relationship
let specificPersonDogs = specificPerson!.dogs
let firstDog = specificPersonDogs[0]
print("# dogs: \(specificPersonDogs.count)")
print("First dog's name: \(firstDog.name)")

```

### Query an Inverse Relationship
You can query through an inverse relationship the same way you would
access a member of a regular Swift or Objective-C object.

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

// Establish a relationship
Person *person = [[Person alloc] init];
person._id = 12345;

DogClub *club = [[DogClub alloc] init];
club.name = @"Pooch Pals";
[club.members addObject:person];

[realm transactionWithBlock:^() {
    [realm addObject:club];
}];

// Later, query the specific person
Person *specificPerson = [Person objectForPrimaryKey:@12345];
    
// Access directly through an inverse relationship
NSLog(@"# memberships: %lu", [specificPerson.clubs count]);
NSLog(@"First club's name: %@", [specificPerson.clubs[0] name]);

```

#### Swift

```swift
let realm = try! Realm()

// Establish an inverse relationship
let person = Person()
person.id = 12345

let club = DogClub()
club.name = "Pooch Pals"
club.members.append(person)

try! realm.write {
    realm.add(club)
}

// Later, query the specific person
let specificPerson = realm.object(ofType: Person.self, forPrimaryKey: 12345)

// Access directly through an inverse relationship
let clubs = specificPerson!.clubs
let firstClub = clubs[0]
print("# memberships: \(clubs.count)")
print("First club's name: \(firstClub.name)")

```

### Query a Collection on Embedded Object Properties
Use dot notation to filter or sort a collection of objects based on an embedded object
property value:

> Note:
> It is not possible to query embedded objects directly. Instead,
access embedded objects through a query for the parent object type.
>

#### Swift

> Version added: 10.19.0

```swift
// Open the default realm
let realm = try! Realm()

// Get all contacts in Los Angeles, sorted by street address
let losAngelesPeople = realm.objects(Person.self)
    .where {
        $0.address.city == "Los Angeles"
    }
    .sorted(byKeyPath: "address.street")
print("Los Angeles Person: \(losAngelesPeople)")

```

#### Swift Nspredicate

```swift
// Open the default realm
let realm = try! Realm()

// Get all people in Los Angeles, sorted by street address
let losAngelesPeople = realm.objects(Person.self)
    .filter("address.city = %@", "Los Angeles")
    .sorted(byKeyPath: "address.street")
print("Los Angeles Person: \(losAngelesPeople)")

```

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
RLMResults<Contact *> *losAngelesContacts = [Contact objectsInRealm:realm where:@"address.city = %@", @"Los Angeles"];

losAngelesContacts = [losAngelesContacts sortedResultsUsingKeyPath:@"address.street" ascending:YES]; 
NSLog(@"Los Angeles Contacts: %@", losAngelesContacts);

```

### Query a Map Property
You can iterate and check the values of a realm `map`
as you would a standard [Dictionary](https://developer.apple.com/documentation/swift/dictionary):

```swift
let realm = try! Realm()

let dogs = realm.objects(Dog.self)

// Find dogs who have favorite parks
let dogsWithFavoriteParks = dogs.where {
    $0.favoriteParksByCity.count >= 1
}

for dog in dogsWithFavoriteParks {
    // Check if an entry exists
    if dog.favoriteParksByCity.keys.contains("Chicago") {
        print("\(dog.name) has a favorite park in Chicago")
    }

    // Iterate over entries
    for element in dog.favoriteParksByCity {
        print("\(dog.name)'s favorite park in \(element.key) is \(element.value)")
    }
}

```

### Query a MutableSet Property
You can query a `MutableSet` to check if
it contains an element. If you are working with multiple sets, you can
check for the intersection of two sets, or check whether one set is a subset
of the other set.

```swift
let realm = try! Realm()

// Find dogs who have visited New York
let newYorkDogs = realm.objects(Dog.self).where {
    $0.citiesVisited.contains("New York")
}

// Get some information about the cities they have visited
for dog in newYorkDogs {
    print("Cities \(dog.name) has visited: \(dog.citiesVisited)")
}

// Check whether two dogs have visited some of the same cities.
// Use "intersects" to find out whether the values of the two sets share common elements.
let isInBothCitiesVisited = (dog.citiesVisited.intersects(dog2.citiesVisited))
print("The two dogs have visited some of the same cities: \(isInBothCitiesVisited)")
// Prints "The two dogs have visited some of the same cities: true"

// Or you can check whether a set is a subset of another set. In this example,
// the first dog has visited "New York" and "Toronto", while dog2 has visited both of
// those but also "Toronto" and "Boston".
let isSubset = (dog.citiesVisited.isSubset(of: dog2.citiesVisited))
print("\(dog.name)'s set of cities visited is a subset of \(dog2.name)'s: \(isSubset)")
// Prints "Maui's set of cities visited is a subset of Lita's: true"

```

### Read and Query AnyRealmValue Property
When you read an AnyRealmValue property, check the value's type before doing
anything with it. The Realm Swift SDK provides an `AnyRealmValue enum` that iterates through all of the types the
AnyRealmValue can store.

```swift
let realm = try! Realm()

let dogs = realm.objects(Dog.self)

for dog in dogs {
    // Verify the type of the ``AnyRealmProperty`` when attempting to get it. This
    // returns an object whose property contains the matched type.

    // If you only care about one type, check for that type.
    if case let .string(companion) = dog.companion {
        print("\(dog.name)'s companion is: \(companion)")
        // Prints "Wolfie's companion is: Fluffy the Cat"
    }

    // Or if you want to do something with multiple types of data
    // that could be in the value, switch on the type.
    switch dog.companion {
    case .string:
        print("\(dog.name)'s companion is: \(dog.companion)")
        // Prints "Wolfie's companion is: string("Fluffy the Cat")
    case .object:
        print("\(dog.name)'s companion is: \(dog.companion)")
        // Prints "Fido's companion is: object(Dog { name = Spot })"
    case .none:
        print("\(dog.name) has no companion")
        // Prints "Rex has no companion" and "Spot has no companion"
    default:
        print("\(dog.name)'s companion is another type.")
    }
}

```

You can compare these mixed value types:

- Numeric: int, bool, float, double, decimal
- Byte-based: string, binary
- Time-based: timestamp, objectId

When using the `AnyRealmValue` mixed data type, keep these things in mind:

- `equals` queries match on value and type
- `not equals` queries match objects with either different values or
different types
- realm converts comparable numeric properties where possible. For example,
in a mixed type field, 1 matches all of 1.0, 1, and true.
- String properties do not match numeric queries. For example, in a mixed
type field, 1 does not match "1". "1" does not match 1, 1.0, or true.

### Query Geospatial Data
> Version added: 10.47.0

The Swift SDK provides several shapes to simplify querying
geospatial data. You can use the
`GeoCircle`, `GeoBox`, and `GeoPolygon` shapes to set the boundaries for
your geospatial data queries.

The SDK provides two specialized non-persistable data types to define shapes:

- `GeoPoint`: A struct that represents the coordinates of a point formed by
a pair of doubles consisting of these values: Latitude: ranges between -90 and 90 degrees, inclusive.Longitude: ranges between -180 and 180 degrees, inclusive.
- `RLMDistance`: A helper struct to represent and convert a distance.

#### Define Geospatial Shapes
#### Geocircle

A `GeoCircle` is a circular shape whose bounds originate from a central
`GeoPoint`, and has a size corresponding to a radius measured in
radians. You can use the SDK's convenience `RLMDistance` data type to
easily work with radii in different units.

`RLMDistance` enables you to specify the radius distance for your geo shapes
in one of four units:

- `.degrees`
- `.kilometers`
- `.miles`
- `.radians`

You can optionally use the supplied convenience methods to convert a
measurement to a different distance units.

```swift
// You can create a GeoCircle radius measured in radians.
// This radian distance corresponds with 0.25 degrees.
let smallCircle = GeoCircle(center: (47.3, -121.9), radiusInRadians: 0.004363323)

// You can also create a GeoCircle radius measured with a Distance.
// You can specify a Distance in .degrees, .kilometers, .miles, or .radians.
let largeCircle = GeoCircle(center: GeoPoint(latitude: 47.8, longitude: -122.6)!, radius: Distance.kilometers(44.4)!)

```



#### Geobox

A `GeoBox` is a rectangular shape whose bounds are determined by
coordinates for a bottom-left and a top-right corner.

```swift
let largeBox = GeoBox(bottomLeft: (47.3, -122.7), topRight: (48.1, -122.1))

let smallBoxBottomLeft = GeoPoint(latitude: 47.5, longitude: -122.4)!
let smallBoxTopRight = GeoPoint(latitude: 47.9, longitude: -121.8)
let smallBox = GeoBox(bottomLeft: smallBoxBottomLeft, topRight: smallBoxTopRight!)

```



#### Geopolygon

A `GeoPolygon` is a polygon shape whose bounds consist of an outer
ring, and 0 or more inner holes to exclude from the geospatial query.

A polygon's outer ring must contain at least three segments. The last
and the first `GeoPoint` must be the same, which indicates a closed
polygon. This means that it takes at least four `GeoPoint` values to
construct a polygon.

Inner holes in a `GeoPolygon` must be entirely contained within the
outer ring.

Holes have the following restrictions:

- Holes may not cross. The boundary of a hole may not intersect both the
interior and the exterior of any other hole.
- Holes may not share edges. If a hole contains an edge AB, then no other
hole may contain it.
- Holes may share vertices. However, no vertex may appear twice in a
single hole.
- No hole may be empty.
- Only one nesting is allowed.

```swift
// Create a basic polygon
let basicPolygon = GeoPolygon(outerRing: [
    (48.0, -122.8),
    (48.2, -121.8),
    (47.6, -121.6),
    (47.0, -122.0),
    (47.2, -122.6),
    (48.0, -122.8)
])

// Create a polygon with one hole
let outerRing: [GeoPoint] = [
    GeoPoint(latitude: 48.0, longitude: -122.8)!,
    GeoPoint(latitude: 48.2, longitude: -121.8)!,
    GeoPoint(latitude: 47.6, longitude: -121.6)!,
    GeoPoint(latitude: 47.0, longitude: -122.0)!,
    GeoPoint(latitude: 47.2, longitude: -122.6)!,
    GeoPoint(latitude: 48.0, longitude: -122.8)!
]

let hole: [GeoPoint] = [
    GeoPoint(latitude: 47.8, longitude: -122.6)!,
    GeoPoint(latitude: 47.7, longitude: -122.2)!,
    GeoPoint(latitude: 47.4, longitude: -122.6)!,
    GeoPoint(latitude: 47.6, longitude: -122.5)!,
    GeoPoint(latitude: 47.8, longitude: -122.6)!
]

let polygonWithOneHole = GeoPolygon(outerRing: outerRing, holes: [hole])

// Add a second hole to the polygon
let hole2: [GeoPoint] = [
    GeoPoint(latitude: 47.55, longitude: -122.05)!,
    GeoPoint(latitude: 47.55, longitude: -121.9)!,
    GeoPoint(latitude: 47.3, longitude: -122.1)!,
    GeoPoint(latitude: 47.55, longitude: -122.05)!
]

let polygonWithTwoHoles = GeoPolygon(outerRing: outerRing, holes: [hole, hole2])

```



#### Query with Geospatial Shapes
You can then use these shapes in a geospatial query. You can query geospatial
data in three ways:

- Using the `.geoWithin()` operator with the type-safe Realm Swift Query API
- Using a `.filter()` with RQL
- Using a `.filter()` with an NSPredicate query

The examples below show the results of queries using these two `Company`
objects:

```swift
let company1 = Geospatial_Company()
company1.location = CustomGeoPoint(47.68, -122.35)

let company2 = Geospatial_Company(CustomGeoPoint(47.9, -121.85))

```



#### Geocircle

```swift
let companiesInSmallCircle = realm.objects(Geospatial_Company.self).where {
    $0.location.geoWithin(smallCircle!)
}
print("Number of companies in small circle: \(companiesInSmallCircle.count)")

let companiesInLargeCircle = realm.objects(Geospatial_Company.self)
    .filter("location IN %@", largeCircle)
print("Number of companies in large circle: \(companiesInLargeCircle.count)")

```



#### Geobox

```swift
let companiesInSmallBox = realm.objects(Geospatial_Company.self).where {
    $0.location.geoWithin(smallBox)
}
print("Number of companies in small box: \(companiesInSmallBox.count)")

let filterArguments = NSMutableArray()
filterArguments.add(largeBox)
let companiesInLargeBox = realm.objects(Geospatial_Company.self)
    .filter(NSPredicate(format: "location IN %@", argumentArray: filterArguments as? [Any]))
print("Number of companies in large box: \(companiesInLargeBox.count)")

```



#### Geopolygon

```swift
let companiesInBasicPolygon = realm.objects(Geospatial_Company.self).where {
    $0.location.geoWithin(basicPolygon!)
}
print("Number of companies in basic polygon: \(companiesInBasicPolygon.count)")

let companiesInPolygonWithTwoHoles = realm.objects(Geospatial_Company.self).where {
    $0.location.geoWithin(polygonWithTwoHoles!)
}
print("Number of companies in polygon with two holes: \(companiesInPolygonWithTwoHoles.count)")

```



### Query a Custom Persistable Property
When you use type projection to map unsupported
types to supported types, accessing those properties is often based on the
persisted type.

#### Queries on Realm Objects
When working with projected types, queries operate on the persisted type.
However, you can use the mapped types interchangeably with the persisted
types in arguments in most cases. The exception is queries on embedded
objects.

> Tip:
> Projected types support sorting and aggregates where
the persisted type supports them.
>

```swift
let akcClub = realm.objects(Club.self).where {
    $0.name == "American Kennel Club"
}.first!
// You can use type-safe expressions to check for equality
XCTAssert(akcClub.url == URL(string: "https://akc.org")!)

let clubs = realm.objects(Club.self)
// You can use the persisted property type in NSPredicate query expressions
let akcByUrl = clubs.filter("url == 'https://akc.org'").first!
XCTAssert(akcByUrl.name == "American Kennel Club")

```

#### Queries on Embedded Objects
You can query embedded types on the supported property types within the
object using memberwise equality.

Object link properties support equality comparisons, but do not support
memberwise comparisons. You can query embedded objects for memberwise
equality on all primitive types. You cannot perform memberwise comparison
on objects and collections.

#### Dynamic APIs
Because the schema has no concept of custom type mappings, reading data via
any of the dynamic APIs gives the underlying persisted type. Realm does
support writing mapped types via a dynamic API, and converts the projected
type to the persisted type.

The most common use of the dynamic APIs is migration. You can write projected
types during migration, and Realm converts the projected type to the persisted
type. However, reading data during a migration gives the underlying persisted
type.

## Read an Object Asynchronously
When you use an actor-isolated realm, you can use Swift concurrency features
to asynchronously query objects.

```swift
let actor = try await RealmActor()

// Read objects in functions isolated to the actor and pass primitive values to the caller
func getObjectId(in actor: isolated RealmActor, forTodoNamed name: String) async -> ObjectId {
    let todo = actor.realm.objects(Todo.self).where {
        $0.name == name
    }.first!
    return todo._id
}
let objectId = await getObjectId(in: actor, forTodoNamed: "Keep it safe")

```

If you need to manually advance the state of an observed realm on the main
thread or an actor-isolated realm, call `await realm.asyncRefresh()`.
This updates the realm and outstanding objects managed by the Realm to point to
the most recent data and deliver any applicable notifications.

For more information about working with realm using Swift concurrency features,
refer to Use Realm with Actors - Swift SDK.

## Sort Query Results
A sort operation allows you to configure the order in which Realm
Database returns queried objects. You can sort based on one or more
properties of the objects in the results collection. Realm only
guarantees a consistent order of results if you explicitly sort them.

#### Objective-C

To sort, call [-[RLMResults
sortedResultsUsingKeyPath:ascending:]](https://www.mongodb.com/docs/realm-sdks/objc/latest/Classes/RLMResults.html#/c:objc(cs)RLMResults(im)sortedResultsUsingKeyPath:ascending:)
with the desired key path to sort by.

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

RLMResults *dogs = [Dog allObjectsInRealm:realm];

// Sort dogs by name
RLMResults *dogsSorted = [dogs sortedResultsUsingKeyPath:@"name" ascending:NO];

// You can also sort on the members of linked objects. In this example,
// we sort the dogs by their favorite toys' names.
RLMResults *dogsSortedByFavoriteToyName = [dogs sortedResultsUsingKeyPath:@"favoriteToy.name" ascending:YES];

```

#### Swift

> Version added: 10.11.0

You can sort using the type-safe keyPath by calling
`Results.sorted(by: )` with the
keyPath name and optional sort order:

```swift
let realm = try! Realm()
// Access all dogs in the realm
let dogs = realm.objects(Dog.self)

// Sort by type-safe keyPath
let dogsSorted = dogs.sorted(by: \.name)

```

To sort using the older API, call `Results.sorted(byKeyPath:ascending:)`
with the desired key path to sort by.

```swift
let realm = try! Realm()
// Access all dogs in the realm
let dogs = realm.objects(Dog.self)

let dogsSorted = dogs.sorted(byKeyPath: "name", ascending: false)

// You can also sort on the members of linked objects. In this example,
// we sort the dogs by their favorite toys' names.
let dogsSortedByFavoriteToyName = dogs.sorted(byKeyPath: "favoriteToy.name")

```

> Tip:
> To sort a query based on a property of an embedded object or a related object, use dot-notation as if it
were in a regular, nested object.
>

> Note:
> String sorting and case-insensitive queries are only supported for
character sets in 'Latin Basic', 'Latin Supplement', 'Latin Extended
A', and 'Latin Extended B' (UTF-8 range 0-591).
>

## Section Query Results
You can split results into individual sections. Each section corresponds
to a key generated from a property on the object it represents.

For example, you might add a computed variable to your object to get the
first letter of the `name` property:

```swift
// Computed variable that is not persisted, but only
// used to section query results.
var firstLetter: String {
    return name.first.map(String.init(_:)) ?? ""
}

```

Then, you can create a `SectionedResults`
type-safe collection for that object, and use it to retrieve objects sectioned
by that computed variable:

```swift
var dogsByFirstLetter: SectionedResults<String, Dog>

dogsByFirstLetter = realm.objects(Dog.self).sectioned(by: \.firstLetter, ascending: true)

```

You can get a count of the sections, get a list of keys, or access an individual
`ResultSection` by index:

```swift
let realm = try! Realm()

var dogsByFirstLetter: SectionedResults<String, Dog>

dogsByFirstLetter = realm.objects(Dog.self).sectioned(by: \.firstLetter, ascending: true)

// You can get a count of the sections in the SectionedResults
let sectionCount = dogsByFirstLetter.count

// Get an array containing all section keys for objects that match the query.
let sectionKeys = dogsByFirstLetter.allKeys
// This example realm contains 4 dogs, "Rex", "Wolfie", "Fido", "Spot".
// Prints ["F", "R", "S", "W"]
print(sectionKeys)

// Get a specific key by index position
let sectionKey = dogsByFirstLetter[0].key
// Prints "Key for index 0: F"
print("Key for index 0: \(sectionKey)")

// You can access Results Sections by the index of the key you want in SectionedResults.
// "F" is the key at index position 0. When we access this Results Section, we get dogs whose name begins with "F".
let dogsByF = dogsByFirstLetter[0]
// Prints "Fido"
print(dogsByF.first?.name)

```

You can also section using a callback. This enables you to section a
collection of primitives, or have more control over how the section key is
generated.

```swift
let realm = try! Realm()
let results = realm.objects(Dog.self)
let sectionedResults = results.sectioned(by: { String($0.name.first!) },
                                         sortDescriptors: [SortDescriptor.init(keyPath: "name", ascending: true)])
let sectionKeys = sectionedResults.allKeys

```

You can observe
`SectionedResults` and `ResultsSection` instances, and both conform to
`ThreadConfined`.

## Aggregate Data
You can use Realm's aggregation operators for sophisticated queries
against list properties.

#### Swift

> Version added: 10.19.0

```swift
let realm = try! Realm()

let people = realm.objects(Person.self)

// People whose dogs' average age is 5
people.where {
    $0.dogs.age.avg == 5
}

// People with older dogs
people.where {
    $0.dogs.age.min > 5
}

// People with younger dogs
people.where {
    $0.dogs.age.max < 2
}

// People with many dogs
people.where {
    $0.dogs.count > 2
}

// People whose dogs' ages combined > 10 years
people.where {
    $0.dogs.age.sum > 10
}

```

#### Swift Nspredicate

```swift
let realm = try! Realm()

let people = realm.objects(Person.self)

// People whose dogs' average age is 5
people.filter("dogs.@avg.age == 5")

// People with older dogs
people.filter("dogs.@min.age > 5")

// People with younger dogs
people.filter("dogs.@max.age < 2")

// People with many dogs
people.filter("dogs.@count > 2")

// People whose dogs' ages combined > 10 years
people.filter("dogs.@sum.age > 10")

```

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

RLMResults *people = [Person allObjectsInRealm:realm];

// People whose dogs' average age is 5
[people objectsWhere:@"dogs.@avg.age == 5"];

// People with older dogs
[people objectsWhere:@"dogs.@min.age > 5"];

// People with younger dogs
[people objectsWhere:@"dogs.@max.age < 2"];

// People with many dogs
[people objectsWhere:@"dogs.@count > 2"];

// People whose dogs' ages combined > 10 years
[people objectsWhere:@"dogs.@sum.age > 10"];

```

## Chain Queries
Because results are lazily evaluated, you
can chain several queries together. Unlike traditional databases, this
does not require a separate trip to the database for each successive
query.

> Example:
> To get a result set for tan dogs, and tan dogs whose names start with
'B', chain two queries like this:
>
> #### Swift
>
> > Version added: 10.19.0
>
> ```swift
> let realm = try! Realm()
> let tanDogs = realm.objects(Dog.self).where {
>     $0.color == "tan"
> }
> let tanDogsWithBNames = tanDogs.where {
>     $0.name.starts(with: "B")
> }
>
> ```
>
>
> #### Swift Nspredicate
>
> ```swift
> let realm = try! Realm()
> let tanDogs = realm.objects(Dog.self).filter("color = 'tan'")
> let tanDogsWithBNames = tanDogs.filter("name BEGINSWITH 'B'")
>
> ```
>
>
> #### Objective-C
>
> ```objectivec
> RLMRealm *realm = [RLMRealm defaultRealm];
> RLMResults<Dog *> *tanDogs = [Dog objectsInRealm:realm where:@"color = 'tan'"];
> RLMResults<Dog *> *tanDogsWithBNames = [tanDogs objectsWhere:@"name BEGINSWITH 'B'"];
>
> ```
>
>

## Query Class Projections
To query for class projections in a
realm, pass the metatype instance `YourProjectionName.self` to
`Realm.objects(_)`.
This returns a `Results` object
representing all of the class projection objects in the realm.

```swift
// Retrieve all class projections of the given type `PersonProjection`
let people = realm.objects(PersonProjection.self)
// Use projection data in your view
print(people.first?.firstName)
print(people.first?.homeCity)
print(people.first?.firstFriendsName)

```

> Tip:
> Don't do derived queries on top of class projection results. Instead, run a
query against the Realm object directly and then project the result. If you
try to do a derived query on top of class projection results, querying a
field with the same name and type as the original object works, but querying
a field with a name or type that isn't in the original object fails.
>

---

### Guides Crud Threading (`docs/guides/crud/threading.md`)

# Threading - Swift SDK
To make your iOS and tvOS apps fast and responsive, you must
balance the computing time needed to lay out the visuals and
handle user interactions with the time needed to process
your data and run your business logic. Typically, app
developers spread this work across multiple threads: the
main or UI thread for all of the user interface-related
work, and one or more background threads to compute heavier
workloads before sending it to the UI thread for
presentation. By offloading heavy work to background
threads, the UI thread can remain highly responsive
regardless of the size of the workload. But it can be
notoriously difficult to write thread-safe, performant, and
maintainable multithreaded code that avoids issues like
deadlocking and race conditions. Realm aims to
simplify this for you.

> Seealso:
> As of 10.26.0, Realm provides async write methods to perform background
writes. See: Perform a Background Write. With
async write, you don't need to pass a thread-safe reference or frozen objects
across threads.
>

This page describes how to manually manage realm files and objects across threads.
Realm also supports using a [Swift actor](https://developer.apple.com/documentation/swift/actor)
to manage realm access using Swift concurrency features. For an overview
of Realm's actor support, refer to Use Realm with Actors - Swift SDK.

## Three Rules to Follow
Before exploring Realm's tools for multithreaded apps, you need to
understand and follow these three rules:

Realm's Multiversion Concurrency Control (MVCC)
architecture eliminates the need to lock for read operations. The values you
read will never be corrupted or in a partially-modified state. You can freely
read from the same Realm file on any thread without the need for locks or
mutexes. Unnecessarily locking would be a performance bottleneck since each
thread might need to wait its turn before reading.

You can write to a Realm file from any thread, but there can be only one
writer at a time. Consequently, synchronous write transactions block each
other. A synchronous write on the UI thread may result in your app appearing
unresponsive while it waits for a write on a background thread to complete.

Live objects, collections, and realm instances are
**thread-confined**: that is, they are only valid on the
thread on which they were created. Practically speaking,
this means you cannot pass live instances to other
threads. However, Realm offers several mechanisms for
sharing objects across threads.

## Perform a Background Write
> Version added: 10.26.0

You can add, modify, or delete objects in the background using
`writeAsync`.

With `writeAsync`, you don't need to pass a thread-safe reference or frozen objects
across threads. Instead, call `realm.writeAsync`. You can provide
a completion block for the method to execute on the source thread after
the write completes or fails.

Things to consider when performing background writes:

- Async writes block closing or invalidating the realm
- You can explicitly commit or cancel transactions

```swift
let realm = try! Realm()

// Query for a specific person object on the main thread
let people = realm.objects(Person.self)
let thisPerson = people.where {
    $0.name == "Dachary"
}.first

// Perform an async write to add dogs to that person's dog list.
// No need to pass a thread-safe reference or frozen object.
realm.writeAsync {
    thisPerson?.dogs.append(objectsIn: [
        Dog(value: ["name": "Ben", "age": 13]),
        Dog(value: ["name": "Lita", "age": 9]),
        Dog(value: ["name": "Maui", "age": 1])
    ])
} onComplete: { _ in
    // Confirm the three dogs were successfully added to the person's dogs list
    XCTAssertEqual(thisPerson!.dogs.count, 3)
    // Query for one of the dogs we added and see that it is present
    let dogs = realm.objects(Dog.self)
    let benDogs = dogs.where {
        $0.name == "Ben"
    }
    XCTAssertEqual(benDogs.count, 1)
}

```

### Wait for Async Writes to Complete
The SDK provides a `Bool` to signal whether the realm is currently
performing an async write. The
`isPerformingAsynchronousWriteOperations`
variable becomes `true` after a call to one of:

- `writeAsync`
- `beginAsyncWrite`
- `commitAsyncWrite`

It remains true until all scheduled async write operations have completed.
While this is true, this blocks closing or `invalidating` the realm.

### Commit or Cancel an Async Write
To complete an async write, you or the SDK must call either:

- `commitAsyncWrite`
- `cancelAsyncWrite`

When you use the `writeAsync` method, the SDK handles committing or
canceling the transaction. This provides the convenience of the async write
without the need to manually keep state tied to the scope of the object.
However, while in the `writeAsync` block, you *can* explicitly call
`commitAsyncWrite` or `cancelAsyncWrite`. If you return without
calling one of these methods, `writeAsync` either:

- Commits the write after executing the instructions in the write block
- Returns an error

In either case, this completes the `writeAsync` operation.

For more control over when to commit or cancel the async write transaction,
use the `beginAsyncWrite` method. When you use this method, you must
explicitly commit the transactions. Returning without committing an async
write cancels the transaction. `beginAsyncWrite` returns an ID that you
can pass to `cancelAsyncWrite`.

`commitAsyncWrite` asynchronously commits a write transaction. This is
the step that persists the data to the realm. `commitAsyncWrite` can
take an `onComplete` block. . This block executes on the source thread
once the commit completes or fails with an error.

Calling `commitAsyncWrite` immediately returns. This allows the caller
to proceed while the SDK performs the I/O on a background thread. This method
returns an ID that you can pass to `cancelAsyncWrite`. This cancels the
pending invocation of the completion block. It does not cancel the commit
itself.

You can group sequential calls to `commitAsyncWrite`. Batching these calls
improves write performance; particularly when the batched transactions are
small. To permit grouping transactions, set the `isGroupingAllowed`
parameter to `true`.

You can call `cancelAsyncWrite` on either `beginAsyncWrite` or
`commitAsyncWrite`. When you call it on `beginAsyncWrite`, this cancels
the entire write transaction. When you call it on `commitAsyncWrite`, this
cancels only an `onComplete` block you may have passed to
`commitAsyncWrite`. It does not cancel the commit itself. You need the ID
of the `beginAsyncWrite` or the `commitAsyncWrite` you want to cancel.

## Communication Across Threads
To access the same Realm file from different threads, you must instantiate a
realm instance on every thread that needs access. As long as you specify the same
configuration, all realm instances will map to the same file on disk.

One of the key rules when working with Realm in a multithreaded
environment is that objects are thread-confined: **you cannot access the
instances of a realm, collection, or object that originated on other threads.**
Realm's Multiversion Concurrency Control (MVCC)
architecture means that there could be many active versions of an object at any
time. Thread-confinement ensures that all instances in that thread are of the
same internal version.

When you need to communicate across threads, you have several options depending
on your use case:

- To modify an object on two threads, query
for the object on both threads.
- To react to changes made on any thread, use Realm's
notifications.
- To see changes that happened on another thread in the current thread's realm
instance, refresh your realm instance.
- To send a fast, read-only view of the object to other threads,
"freeze" the object.
- To keep and share many read-only views of the object in your app, copy
the object from the realm.
- To share an instance of a realm or specific object with another thread or
across actor boundaries, share a thread-safe reference to the realm instance or object. For more
information, refer to Pass a ThreadSafeReference.

### Create a Serial Queue to use Realm on a Background Thread
When using Realm on a background thread, create a serial queue. Realm
does not support using realms in concurrent queues, such as the `global()`
queue.

```swift
// Initialize a serial queue, and
// perform realm operations on it
let serialQueue = DispatchQueue(label: "serial-queue")
serialQueue.async {
    let realm = try! Realm(configuration: .defaultConfiguration, queue: serialQueue)
    // Do something with Realm on the non-main thread
}

```

### Pass Instances Across Threads
Instances of `Realm`, `Results`, `List`, and managed `Objects`
are *thread-confined*. That means you may only use them on the thread
where you created them. However, Realm provides a mechanism called
**thread-safe references** that allows you to copy an instance
created on one thread to another thread.

#### Sendable Conformance
> Version added: 10.20.0
> @ThreadSafe wrapper and ThreadSafeReference conform to `Sendable`
>

If you are using Swift 5.6 or higher, both the `@ThreadSafe
property wrapper` and
`ThreadSafeReference`
conform to [Sendable](https://developer.apple.com/documentation/swift/sendable).

#### Use the @ThreadSafe Wrapper
> Version added: 10.17.0

You can pass thread-confined instances to another thread as follows:

1. Use the `@ThreadSafe` property wrapper to declare a variable that references the original object. By definition, `@ThreadSafe`-wrapped variables are always optional.
2. Pass the `@ThreadSafe`-wrapped variable to the other thread.
3. Use the `@ThreadSafe`-wrapped variable as you would any optional. If the referenced object is removed from the realm, the referencing variable becomes nil.

```swift
let realm = try! Realm()

let person = Person(name: "Jane")
try! realm.write {
    realm.add(person)
}

// Create thread-safe reference to person
@ThreadSafe var personRef = person

// @ThreadSafe vars are always optional. If the referenced object is deleted,
// the @ThreadSafe var will be nullified.
print("Person's name: \(personRef?.name ?? "unknown")")

// Pass the reference to a background thread
DispatchQueue(label: "background", autoreleaseFrequency: .workItem).async {
    let realm = try! Realm()
    try! realm.write {
        // Resolve within the transaction to ensure you get the
        // latest changes from other threads. If the person
        // object was deleted, personRef will be nil.
        guard let person = personRef else {
            return // person was deleted
        }
        person.name = "Jane Doe"
    }
}

```

Another way to work with an object on another thread is to query for it
again on that thread. But if the object does not have a primary
key, it is not trivial to
query for it. You can use the `@ThreadSafe` wrapper on any object,
regardless of whether it has a primary key.

> Example:
> The following example shows how to use `@ThreadSafe` on a function
parameter. This is useful for functions that may run asynchronously
or on another thread.
>
> > Tip:
> > If your app accesses Realm in an `async/await` context, mark the code
with `@MainActor` to avoid threading-related crashes.
> >
>
> ```swift
> func someLongCallToGetNewName() async -> String {
>     return "Janet"
> }
>
> @MainActor
> func loadNameInBackground(@ThreadSafe person: Person?) async {
>     let newName = await someLongCallToGetNewName()
>     let realm = try! await Realm()
>     try! realm.write {
>         person?.name = newName
>     }
> }
>
> @MainActor
> func createAndUpdatePerson() async {
>     let realm = try! await Realm()
>
>     let person = Person(name: "Jane")
>     try! realm.write {
>         realm.add(person)
>     }
>     await loadNameInBackground(person: person)
> }
>
> await createAndUpdatePerson()
>
> ```
>

#### Use ThreadSafeReference (Legacy Swift / Objective-C)
Before Realm Swift SDK version 10.17.0 or in Objective-C, you can pass
thread-confined instances to another thread as follows:

1. Initialize a `ThreadSafeReference` with the thread-confined object.
2. Pass the reference to the other thread or queue.
3. Resolve the reference on the other thread's realm by calling `Realm.resolve(_:)`. Use the returned object as normal.

> Important:
> You must resolve a `ThreadSafeReference` exactly once. Otherwise,
the source realm remains pinned until the reference gets
deallocated. For this reason, `ThreadSafeReference` should be
short-lived.
>

```swift
let person = Person(name: "Jane")
let realm = try! Realm()

try! realm.write {
    realm.add(person)
}

// Create thread-safe reference to person
let personRef = ThreadSafeReference(to: person)

// Pass the reference to a background thread
DispatchQueue(label: "background", autoreleaseFrequency: .workItem).async {
    let realm = try! Realm()
    try! realm.write {
        // Resolve within the transaction to ensure you get the latest changes from other threads
        guard let person = realm.resolve(personRef) else {
            return // person was deleted
        }
        person.name = "Jane Doe"
    }
}

```

Another way to work with an object on another thread is to query for it
again on that thread. But if the object does not have a primary
key, it is not trivial to
query for it. You can use `ThreadSafeReference` on any object,
regardless of whether it has a primary key. You can also use it with
lists and results.

The downside is that `ThreadSafeReference` requires some boilerplate.
You must remember to wrap everything in a `DispatchQueue` with a
properly-scoped `autoreleaseFrequency` so the objects do not linger on
the background thread. So, it can be helpful to make a convenience extension
to handle the boilerplate as follows:

```swift
extension Realm {
    func writeAsync<T: ThreadConfined>(_ passedObject: T, errorHandler: @escaping ((_ error: Swift.Error) -> Void) = { _ in return }, block: @escaping ((Realm, T?) -> Void)) {
        let objectReference = ThreadSafeReference(to: passedObject)
        let configuration = self.configuration
        DispatchQueue(label: "background", autoreleaseFrequency: .workItem).async {
            do {
                let realm = try Realm(configuration: configuration)
                try realm.write {
                    // Resolve within the transaction to ensure you get the latest changes from other threads
                    let object = realm.resolve(objectReference)
                    block(realm, object)
                }
            } catch {
                errorHandler(error)
            }
        }
    }
}

```

This extension adds a `writeAsync()` method to the Realm class. This
method passes an instance to a background thread for you.

> Example:
> Suppose you made an email app and want to delete all read emails in
the background. You can now do it with two lines of code. Note that
the closure runs on the background thread and receives its own
version of both the realm and passed object:
>
> ```swift
> let realm = try! Realm()
> let readEmails = realm.objects(Email.self).where {
>     $0.read == true
> }
> realm.writeAsync(readEmails) { (realm, readEmails) in
>     guard let readEmails = readEmails else {
>         // Already deleted
>         return
>     }
>     realm.delete(readEmails)
> }
>
> ```
>

### Use the Same Realm Across Threads
You cannot share realm instances across threads.

To use the same Realm file across threads, open a different realm
instance on each thread. As long as you use the same
`configuration`, all Realm
instances will map to the same file on disk.

### Refreshing Realms
When you open a realm, it reflects the most recent successful write
commit and remains on that version until it is **refreshed**. This means
that the realm will not see changes that happened on another thread
until the next refresh. A realm on the UI thread -- more precisely,
on any event loop thread -- automatically refreshes itself at
the beginning of that thread's loop. However, you must manually refresh
realm instances that do not exist on loop threads or that have
auto-refresh disabled.

#### Objective-C

```objective-c
if (![realm autorefresh]) {
    [realm refresh]
}
```

#### Swift

```swift
if (!realm.autorefresh) {
   // Manually refresh
   realm.refresh()
}
```

### Frozen Objects
Live, thread-confined objects work fine in most cases.
However, some apps -- those based on reactive, event
stream-based architectures, for example -- need to send
immutable copies around to many threads for processing
before ultimately ending up on the UI thread. Making a deep
copy every time would be expensive, and Realm does not allow
live instances to be shared across threads. In this case,
you can **freeze** and **thaw** objects, collections, and realms.

Freezing creates an immutable view of a specific object,
collection, or realm. The frozen object, collection, or realm still
exists on disk, and does not need to be deeply copied when passed around
to other threads. You can freely share the frozen object across threads
without concern for thread issues. When you freeze a realm, its child
objects also become frozen.

> Tip:
> Realm does not currently support using `thaw()` with Swift Actors.
To work with Realm data across actor boundaries, use
`ThreadSafeReference` instead of frozen objects. For more information,
refer to Pass a ThreadSafeReference.
>

Frozen objects are not live and do not automatically update.
They are effectively snapshots of the object state at the
time of freezing. Thawing an object returns a live version of the frozen
object.

#### Objective-C

```objectivec
// Get an immutable copy of the realm that can be passed across threads
RLMRealm *frozenRealm = [realm freeze];

RLMResults *dogs = [Dog allObjectsInRealm:realm];

// You can freeze collections
RLMResults *frozenDogs = [dogs freeze];

// You can still read from frozen realms
RLMResults *frozenDogs2 = [Dog allObjectsInRealm:frozenRealm];

Dog *dog = [dogs firstObject];

// You can freeze objects
Dog *frozenDog = [dog freeze];

// To modify frozen objects, you can thaw them
// You can thaw collections
RLMResults *thawedDogs = [dogs thaw];

// You can thaw objects
Dog *thawedDog = [dog thaw];

// You can thaw frozen realms
RLMRealm *thawedRealm = [realm thaw];
```

#### Swift

```swift
let realm = try! Realm()

// Get an immutable copy of the realm that can be passed across threads
let frozenRealm = realm.freeze()

assert(frozenRealm.isFrozen)

let people = realm.objects(Person.self)

// You can freeze collections
let frozenPeople = people.freeze()

assert(frozenPeople.isFrozen)

// You can still read from frozen realms
let frozenPeople2 = frozenRealm.objects(Person.self)

assert(frozenPeople2.isFrozen)

let person = people.first!

assert(!person.realm!.isFrozen)

// You can freeze objects
let frozenPerson = person.freeze()

assert(frozenPerson.isFrozen)
// Frozen objects have a reference to a frozen realm
assert(frozenPerson.realm!.isFrozen)

```

When working with frozen objects, an attempt to do any of
the following throws an exception:

- Opening a write transaction on a frozen realm.
- Modifying a frozen object.
- Adding a change listener to a frozen realm, collection, or object.

You can use `isFrozen` to check if the object is frozen. This is always
thread-safe.

#### Objective-C

```objective-c
if ([realm isFrozen]) {
    // ...
}
```

#### Swift

```swift
if (realm.isFrozen) {
    // ...
}
```

Frozen objects remain valid as long as the live realm that
spawned them stays open. Therefore, avoid closing the live
realm until all threads are done with the frozen objects.
You can close a frozen realm before the live realm is closed.

> Important:
> Caching too many frozen objects can have a negative
impact on the realm file size. "Too many" depends on your
specific target device and the size of your Realm
objects. If you need to cache a large number of versions,
consider copying what you need out of the realm instead.
>

#### Modify a Frozen Object
To modify a frozen object, you must thaw the object. Alternately, you can
query for it on an unfrozen realm, then modify it. Calling `thaw`
on a live object, collection, or realm returns itself.

Thawing an object or collection also thaws the realm it references.

```swift
// Read from a frozen realm
let frozenPeople = frozenRealm.objects(Person.self)

// The collection that we pull from the frozen realm is also frozen
assert(frozenPeople.isFrozen)

// Get an individual person from the collection
let frozenPerson = frozenPeople.first!

// To modify the person, you must first thaw it
// You can also thaw collections and realms
let thawedPerson = frozenPerson.thaw()

// Check to make sure this person is valid. An object is
// invalidated when it is deleted from its managing realm,
// or when its managing realm has invalidate() called on it.
assert(thawedPerson?.isInvalidated == false)

// Thawing the person also thaws the frozen realm it references
assert(thawedPerson!.realm!.isFrozen == false)

// Let's make the code easier to follow by naming the thawed realm
let thawedRealm = thawedPerson!.realm!

// Now, you can modify the todo
try! thawedRealm.write {
   thawedPerson!.name = "John Michael Kane"
}

```

#### Append to a Frozen Collection
When you append to a frozen collection,
you must thaw both the collection and the object that you want to append.
In this example, we query for two objects in a frozen Realm:

- A Person object that has a List property
of Dog objects
- A Dog object

We must thaw both objects before we can append the Dog to
the Dog List collection on the Person. If we thaw only the Person object
but not the Dog, Realm throws an error.

The same rule applies when passing frozen objects across threads. A common
case might be calling a function on a background thread to do some work
instead of blocking the UI.

```swift
// Get a copy of frozen objects.
// Here, we're getting them from a frozen realm,
// but you might also be passing them across threads.
let frozenTimmy = frozenRealm.objects(Person.self).where {
    $0.name == "Timmy"
}.first!
let frozenLassie = frozenRealm.objects(Dog.self).where {
    $0.name == "Lassie"
}.first!
// Confirm the objects are frozen.
assert(frozenTimmy.isFrozen == true)
assert(frozenLassie.isFrozen == true)
// Thaw the frozen objects. You must thaw both the object
// you want to append and the collection you want to append it to.
let thawedTimmy = frozenTimmy.thaw()
let thawedLassie = frozenLassie.thaw()
let realm = try! Realm()
try! realm.write {
    thawedTimmy?.dogs.append(thawedLassie!)
}
XCTAssertEqual(thawedTimmy?.dogs.first?.name, "Lassie")

```

## Realm's Threading Model in Depth
Realm provides safe, fast, lock-free, and concurrent access
across threads with its [Multiversion Concurrency
Control (MVCC)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control)
architecture.

### Compared and Contrasted with Git
If you are familiar with a distributed version control
system like [Git](https://git-scm.com/), you may already
have an intuitive understanding of MVCC. Two fundamental
elements of Git are:

- Commits, which are atomic writes.
- Branches, which are different versions of the commit history.

Similarly, Realm has atomically-committed writes in the form
of transactions. Realm also has many
different versions of the history at any given time, like
branches.

Unlike Git, which actively supports distribution and
divergence through forking, a realm only has one true latest
version at any given time and always writes to the head of
that latest version. Realm cannot write to a previous
version. This means your data converges on one
latest version of the truth.

### Internal Structure
A realm is implemented using a [B+ tree](https://en.wikipedia.org/wiki/B%2B_tree) data structure. The top-level node represents a
version of the realm; child nodes are objects in that
version of the realm. The realm has a pointer to its latest
version, much like how Git has a pointer to its HEAD commit.

Realm uses a copy-on-write technique to ensure
[isolation](https://en.wikipedia.org/wiki/Isolation_(database_systems)) and
[durability](https://en.wikipedia.org/wiki/Durability_(database_systems)).
When you make changes, Realm copies the relevant part of the
tree for writing. Realm then commits the changes in two
phases:

- Realm writes changes to disk and verifies success.
- Realm then sets its latest version pointer to point to the newly-written version.

This two-step commit process guarantees that even if the
write failed partway, the original version is not corrupted
in any way because the changes were made to a copy of the
relevant part of the tree. Likewise, the realm's root
pointer will point to the original version until the new
version is guaranteed to be valid.

> Example:
> The following diagram illustrates the commit process:
>
> 
>
> 1. The realm is structured as a tree. The realm has a pointer
to its latest version, V1.
> 2. When writing, Realm creates a new version V2 based on V1.
Realm makes copies of objects for modification (A 1,
C 1),  while links to unmodified objects continue to
point to the original versions (B, D).
> 3. After validating the commit, Realm updates the
pointer to the new latest version, V2. Realm then discards
old nodes no longer connected to the tree.
>

Realm uses zero-copy techniques
like memory mapping to handle data. When you read a value
from the realm, you are virtually looking at the value on
the actual disk, not a copy of it. This is the basis for
live objects. This is also why a realm
head pointer can be set to point to the new version after
the write to disk has been validated.

## Summary
- Realm enables simple and safe multithreaded code when you follow
these rules: don't lock to readavoid writes on the UI thread if you
write on background threads, and don't pass live objects to other threads.
- There is a proper way to share objects across threads for each use case.
- In order to see changes made on other threads in your realm
instance, you must manually **refresh** realm instances that do
not exist on "loop" threads or that have auto-refresh disabled.
- For apps based on reactive, event-stream-based architectures, you can
**freeze** objects, collections, and realms in order to pass
shallow copies around efficiently to different threads for processing.
- Realm's multiversion concurrency control (MVCC)
architecture is similar to Git's. Unlike Git, Realm has
only one true latest version for each realm.
- Realm commits in two stages to guarantee isolation and durability.

## Sendable, Non-Sendable and Thread-Confined Types
The Realm Swift SDK public API contains types that fall into three broad
categories:

- Sendable
- Not Sendable and not thread confined
- Thread-confined

You can share types that are not Sendable and not thread confined between
threads, but you must synchronize them.

Thread-confined types, unless frozen, are confined to an isolation context.
You cannot pass them between these contexts even with synchronization.

---

### Guides Crud Update (`docs/guides/crud/update.md`)

# CRUD - Update - Swift SDK
## Update Realm Objects
Updates to Realm Objects must occur within write transactions. For
more information about write transactions, see: Transactions.

### About The Examples On This Page
The examples on this page use the following models:

#### Objective-C

```objectivec
// DogToy.h
@interface DogToy : RLMObject
@property NSString *name;
@end

// Dog.h
@interface Dog : RLMObject
@property NSString *name;
@property int age;
@property NSString *color;

// To-one relationship
@property DogToy *favoriteToy;

@end

// Enable Dog for use in RLMArray
RLM_COLLECTION_TYPE(Dog)

// Person.h
// A person has a primary key ID, a collection of dogs, and can be a member of multiple clubs.
@interface Person : RLMObject
@property int _id;
@property NSString *name;

// To-many relationship - a person can have many dogs
@property RLMArray<Dog *><Dog> *dogs;

// Inverse relationship - a person can be a member of many clubs
@property (readonly) RLMLinkingObjects *clubs;
@end

RLM_COLLECTION_TYPE(Person)

// DogClub.h
@interface DogClub : RLMObject
@property NSString *name;
@property RLMArray<Person *><Person> *members;
@end

// Dog.m
@implementation Dog
@end

// DogToy.m
@implementation DogToy
@end

// Person.m
@implementation Person
// Define the primary key for the class
+ (NSString *)primaryKey {
    return @"_id";
}

// Define the inverse relationship to dog clubs
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"clubs": [RLMPropertyDescriptor descriptorWithClass:DogClub.class propertyName:@"members"],
    };
}
@end

// DogClub.m
@implementation DogClub
@end

```

#### Swift

```swift
class Dog: Object {
    @Persisted var name = ""
    @Persisted var age = 0
    @Persisted var color = ""
    @Persisted var currentCity = ""
    @Persisted var citiesVisited: MutableSet<String>
    @Persisted var companion: AnyRealmValue

    // Map of city name -> favorite park in that city
    @Persisted var favoriteParksByCity: Map<String, String>
}

class Person: Object {
    @Persisted(primaryKey: true) var id = 0
    @Persisted var name = ""

    // To-many relationship - a person can have many dogs
    @Persisted var dogs: List<Dog>

    // Embed a single object.
    // Embedded object properties must be marked optional.
    @Persisted var address: Address?
}

class Address: EmbeddedObject {
    @Persisted var street: String?
    @Persisted var city: String?
    @Persisted var country: String?
    @Persisted var postalCode: String?
}

```

### Update an Object
You can modify properties of a Realm object inside of a write
transaction in the same way that you would update any other Swift or
Objective-C object.

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
// Open a thread-safe transaction.
[realm transactionWithBlock:^{
    // Get a dog to update.
    Dog *dog = [[Dog allObjectsInRealm: realm] firstObject];

    // Update some properties on the instance.
    // These changes are saved to the realm.
    dog.name = @"Wolfie";
    dog.age += 1;
}];

```

#### Swift

```swift
let realm = try! Realm()

// Get a dog to update
let dog = realm.objects(Dog.self).first!

// Open a thread-safe transaction
try! realm.write {
    // Update some properties on the instance.
    // These changes are saved to the realm
    dog.name = "Wolfie"
    dog.age += 1
}

```

> Tip:
> To update a property of an embedded object or a related object, modify the property with
dot-notation or bracket-notation as if it were in a regular, nested
object.
>

### Update Properties with Key-value Coding
`Object`, `Result`, and `List` all conform to
[key-value coding](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueCoding/).
This can be useful when you need to determine which property to update
at runtime.

Applying KVC to a collection is a great way to update objects in bulk.
Avoid the overhead of iterating over a collection while creating
accessors for every item.

```swift
let realm = try! Realm()

let allDogs = realm.objects(Dog.self)

try! realm.write {
    allDogs.first?.setValue("Sparky", forKey: "name")
    // Move the dogs to Toronto for vacation
    allDogs.setValue("Toronto", forKey: "currentCity")
}

```

You can also add values for embedded objects or relationships this
way. In this example, we add a collection to an object's list property:

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];

[realm transactionWithBlock:^() {
    // Create a person to take care of some dogs.
    Person *ali = [[Person alloc] initWithValue:@{@"_id": @1, @"name": @"Ali"}];
    [realm addObject:ali];

    // Find dogs younger than 2.
    RLMResults<Dog *> *puppies = [Dog objectsInRealm:realm where:@"age < 2"];

    // Batch update: give all puppies to Ali.
    [ali setValue:puppies forKey:@"dogs"];
}];

```

#### Swift

```swift
let realm = try! Realm()
try! realm.write {
    // Create a person to take care of some dogs.
    let person = Person(value: ["id": 1, "name": "Ali"])
    realm.add(person)

    let dog = Dog(value: ["name": "Rex", "age": 1])
    realm.add(dog)

    // Find dogs younger than 2.
    let puppies = realm.objects(Dog.self).filter("age < 2")

    // Give all puppies to Ali.
    person.setValue(puppies, forKey: "dogs")

}

```

### Upsert an Object
An **upsert** either inserts or updates an object depending on whether
the object already exists. Upserts require the data model to have a
primary key.

#### Objective-C

To upsert an object, call `-[RLMRealm addOrUpdateObject:]`.

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
    Person *jones = [[Person alloc] initWithValue:@{@"_id": @1234, @"name": @"Jones"}];
    // Add a new person to the realm. Since nobody with ID 1234
    // has been added yet, this adds the instance to the realm.
    [realm addOrUpdateObject:jones];
    
    Person *bowie = [[Person alloc] initWithValue:@{@"_id": @1234, @"name": @"Bowie"}];
    // Judging by the ID, it's the same person, just with a different name.
    // This overwrites the original entry (i.e. Jones -> Bowie).
    [realm addOrUpdateObject:bowie];
}];

```

#### Swift

To upsert an object, call `Realm.add(_:update:)`
with the second parameter, update policy, set to `.modified`.

```swift
let realm = try! Realm()
try! realm.write {
    let person1 = Person(value: ["id": 1234, "name": "Jones"])
    // Add a new person to the realm. Since nobody with ID 1234
    // has been added yet, this adds the instance to the realm.
    realm.add(person1, update: .modified)

    let person2 = Person(value: ["id": 1234, "name": "Bowie"])
    // Judging by the ID, it's the same person, just with a
    // different name. When `update` is:
    // - .modified: update the fields that have changed.
    // - .all: replace all of the fields regardless of
    //   whether they've changed.
    // - .error: throw an exception if a key with the same
    //   primary key already exists.
    realm.add(person2, update: .modified)
}

```

You can also partially update an object by passing the primary key and a
subset of the values to update:

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
    // Only update the provided values.
    // Note that the "name" property will remain the same
    // for the person with primary key "_id" 123.
    [Person createOrUpdateModifiedInRealm:realm
        withValue:@{@"_id": @123, @"dogs": @[@[@"Buster", @5]]}];
}];

```

#### Swift

```swift
let realm = try! Realm()
try! realm.write {
    // Use .modified to only update the provided values.
    // Note that the "name" property will remain the same
    // for the person with primary key "id" 123.
    realm.create(Person.self,
                 value: ["id": 123, "dogs": [["Buster", 5]]],
                 update: .modified)
}

```

### Update a Map/Dictionary
You can update a realm `map` as you would a
standard [Dictionary](https://developer.apple.com/documentation/swift/dictionary):

```swift
let realm = try! Realm()

// Find the dog we want to update
let wolfie = realm.objects(Dog.self).where {
    $0.name == "Wolfie"
}.first!

print("Wolfie's favorite park in New York is: \(wolfie.favoriteParksByCity["New York"])")
XCTAssertTrue(wolfie.favoriteParksByCity["New York"] == "Domino Park")

// Update values for keys, or add values if the keys do not currently exist
try! realm.write {
    wolfie.favoriteParksByCity["New York"] = "Washington Square Park"
    wolfie.favoriteParksByCity.updateValue("A Street Park", forKey: "Boston")
    wolfie.favoriteParksByCity.setValue("Little Long Pond", forKey: "Seal Harbor")
}

XCTAssertTrue(wolfie.favoriteParksByCity["New York"] == "Washington Square Park")

```

### Update a MutableSet Property
You can `insert` elements into a `MutableSet` during write transactions to add them to the
property. If you are working with multiple sets, you can also insert or
remove set elements contained in one set from the other set. Alternately,
you can mutate a set to contain only the common elements from both.

```swift
let realm = try! Realm()

// Record a dog's name, current city, and store it to the cities visited.
let dog = Dog()
dog.name = "Maui"
dog.currentCity = "New York"
try! realm.write {
    realm.add(dog)
    dog.citiesVisited.insert(dog.currentCity)
}

// Update the dog's current city, and add it to the set of cities visited.
try! realm.write {
    dog.currentCity = "Toronto"
    dog.citiesVisited.insert(dog.currentCity)
}
XCTAssertEqual(dog.citiesVisited.count, 2)

// If you're operating with two sets, you can insert the elements from one set into another set.
// The dog2 set contains one element that isn't present in the dog set.
try! realm.write {
    dog.citiesVisited.formUnion(dog2.citiesVisited)
}
XCTAssertEqual(dog.citiesVisited.count, 3)

// Or you can remove elements that are present in the second set. This removes the one element
// that we added above from the dog2 set.
try! realm.write {
    dog.citiesVisited.subtract(dog2.citiesVisited)
}
XCTAssertEqual(dog.citiesVisited.count, 2)

// If the sets contain common elements, you can mutate the set to only contain those common elements.
// In this case, the two sets contain no common elements, so this set should now contain 0 items.
try! realm.write {
    dog.citiesVisited.formIntersection(dog2.citiesVisited)
}
XCTAssertEqual(dog.citiesVisited.count, 0)

```

### Update an AnyRealmValue Property
You can update an AnyRealmValue property through assignment, but you must
specify the type of the value when you assign it. The Realm Swift SDK
provides an `AnyRealmValue enum` that
iterates through all of the types the AnyRealmValue can store.

```swift
let realm = try! Realm()

// Get a dog to update
let rex = realm.objects(Dog.self).where {
    $0.name == "Rex"
}.first!

try! realm.write {
    // As with creating an object with an AnyRealmValue, you must specify the
    // type of the value when you update the property.
    rex.companion = .object(Dog(value: ["name": "Regina"]))
}

```

### Update an Embedded Object Property
To update a property in an embedded object, modify the property in a
write transaction. If the embedded object is null, updating an embedded
object property has no effect.

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock: ^{
    Contact *contact = [Contact objectInRealm:realm
                                forPrimaryKey:[[RLMObjectId alloc] initWithString:@"5f481c21f634a1f4eeaa7268" error:nil]];
    contact.address.street = @"Hollywood Upstairs Medical College";
    contact.address.city = @"Los Angeles";
    contact.address.postalCode = @"90210";
    NSLog(@"Updated contact: %@", contact);
}];

```

#### Swift

```swift
// Open the default realm
let realm = try! Realm()

let idOfPersonToUpdate = 123

// Find the person to update by ID
guard let person = realm.object(ofType: Person.self, forPrimaryKey: idOfPersonToUpdate) else {
    print("Person \(idOfPersonToUpdate) not found")
    return
}

try! realm.write {
    // Update the embedded object directly through the person
    // If the embedded object is null, updating these properties has no effect
    person.address?.street = "789 Any Street"
    person.address?.city = "Anytown"
    person.address?.postalCode = "12345"
    print("Updated person: \(person)")
}

```

### Overwrite an Embedded Object
To overwrite an embedded object, reassign the embedded object property
of a party to a new instance in a write transaction.

#### Objective-C

```objectivec
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock: ^{
    Contact *contact = [Contact objectInRealm:realm
                                forPrimaryKey:[[RLMObjectId alloc] initWithString:@"5f481c21f634a1f4eeaa7268" error:nil]];
    Address *newAddress = [[Address alloc] init];
    newAddress.street = @"Hollywood Upstairs Medical College";
    newAddress.city = @"Los Angeles";
    newAddress.country = @"USA";
    newAddress.postalCode = @"90210";
    contact.address = newAddress;
    NSLog(@"Updated contact: %@", contact);
}];

```

#### Swift

```swift
// Open the default realm
let realm = try! Realm()

let idOfPersonToUpdate = 123

// Find the person to update by ID
guard let person = realm.object(ofType: Person.self, forPrimaryKey: idOfPersonToUpdate) else {
    print("Person \(idOfPersonToUpdate) not found")
    return
}

try! realm.write {
    let newAddress = Address()
    newAddress.street = "789 Any Street"
    newAddress.city = "Anytown"
    newAddress.country = "USA"
    newAddress.postalCode = "12345"

    // Overwrite the embedded object
    person.address = newAddress
    print("Updated person: \(person)")
}

```

## Update an Object Asynchronously
You can use Swift concurrency features to asynchronously update objects
using an actor-isolated realm.

This function from the example `RealmActor` defined on the
Use Realm with Actors page shows how you might
update an object in an actor-isolated realm:

```swift
func updateTodo(_id: ObjectId, name: String, owner: String, status: String) async throws {
    try await realm.asyncWrite {
        realm.create(Todo.self, value: [
            "_id": _id,
            "name": name,
            "owner": owner,
            "status": status
        ], update: .modified)
    }
}

```

And you might perform this update using Swift's async syntax:

```swift
let actor = try await RealmActor()

// Read objects in functions isolated to the actor and pass primitive values to the caller
func getObjectId(in actor: isolated RealmActor, forTodoNamed name: String) async -> ObjectId {
    let todo = actor.realm.objects(Todo.self).where {
        $0.name == name
    }.first!
    return todo._id
}
let objectId = await getObjectId(in: actor, forTodoNamed: "Keep it safe")

try await actor.updateTodo(_id: objectId, name: "Keep it safe", owner: "Frodo", status: "Completed")

```

This operation does not block or perform I/O on the calling thread. For
more information about writing to realm using Swift concurrency features,
refer to Use Realm with Actors - Swift SDK.

## Update Properties through Class Projections
### Change Class Projection Properties
You can make changes to a class projection's properties in a write transaction.

```swift
// Retrieve all class projections of the given type `PersonProjection`
// and filter for the first class projection where the `firstName` property
// value is "Jason"
let person = realm.objects(PersonProjection.self).first(where: { $0.firstName == "Jason" })!
// Update class projection property in a write transaction
try! realm.write {
    person.firstName = "David"
}

```

---

### Guides Model Data Change An Object Model (`docs/guides/model-data/change-an-object-model.md`)

# Change an Object Model - Swift SDK

## Overview
When you update your object schema, you must increment the schema version
and perform a migration.

> Seealso:
> This page provides general Swift and Objective-C migration examples.
If you are using Realm with SwiftUI, see the SwiftUI-specific
migration examples.
>

If your schema update adds optional properties or removes properties,
Realm can perform the migration automatically. You only need to
increment the `schemaVersion`.

For more complex schema updates, you must also manually specify the migration logic
in a `migrationBlock`. This might include changes such as:

- Adding required properties that must be populated with default values
- Combining fields
- Renaming a field
- Changing a field's type
- Converting from an object to an embedded object

> Tip:
> When developing or debugging your application, you may prefer to delete
the realm instead of migrating it. Use the
`deleteRealmIfMigrationNeeded`
flag to delete the database automatically when a schema mismatch would
require a migration.
>
> Never release an app to production with this flag set to `true`.
>

## Schema Version
A **schema version** identifies the state of a Realm Schema at some point in time. Realm tracks the schema
version of each realm and uses it to map the objects in each realm
to the correct schema.

Schema versions are integers that you may include
in the realm configuration when you open a realm. If a client
application does not specify a version number when it opens a realm then
the realm defaults to version `0`.

> Important:
> Migrations must update a realm to a higher schema version.
Realm will throw an error if a client application opens
a realm with a schema version that is lower than the realm's
current version or if the specified schema version is the same as the
realm's current version but includes different object
schemas.
>

### Migrations
Local migrations have access to the existing
Realm Schema, version, and objects and define logic that
incrementally updates the realm to its new schema version.
To perform a local migration you must specify a new schema
version that is higher than the current version and provide
a migration function when you open the out-of-date realm.

In iOS, you can update underlying data to reflect schema changes using
manual migrations. During such a
manual migration, you can define new and deleted properties when they
are added or removed from your schema.

## Automatically Update Schema
### Add a Property
Realm can automatically migrate added
properties, but you must specify an updated schema version when you make
these changes.

> Note:
> Realm does not automatically set values for new required
properties. You must use a migration block to set default values for
new required properties. For new optional properties, existing records
can have null values. This means you don't need a migration block when
adding optional properties.
>

> Example:
> A realm using schema version `1` has a `Person` object type
that has first name, last name, and age properties:
>
> #### Objective-C
>
> ```objectivec
> // In the first version of the app, the Person model
> // has separate fields for first and last names,
> // and an age property.
> @interface Person : RLMObject
> @property NSString *firstName;
> @property NSString *lastName;
> @property int age;
> @end
>
> @implementation Person
> + (NSArray<NSString *> *)requiredProperties {
>     return @[@"firstName", @"lastName", @"age"];
> }
> @end
>
> ```
>
>
> #### Swift
>
> ```swift
> // In the first version of the app, the Person model
> // has separate fields for first and last names,
> // and an age property.
> class Person: Object {
>     @Persisted var firstName = ""
>     @Persisted var lastName = ""
>     @Persisted var age = 0
> }
>
> ```
>
>
> The developer decides that the `Person` class needs an `email` field and updates
the schema.
>
> #### Objective-C
>
> ```objectivec
> // In a new version, you add a property
> // on the Person model.
> @interface Person : RLMObject
> @property NSString *firstName;
> @property NSString *lastName;
> // Add a new "email" property.
> @property NSString *email;
> // New properties can be migrated
> // automatically, but must update the schema version.
> @property int age;
> @end
>
> @implementation Person
> + (NSArray<NSString *> *)requiredProperties {
>     return @[@"firstName", @"lastName", @"email", @"age"];
> }
> @end
>
> ```
>
>
> #### Swift
>
> ```swift
> // In a new version, you add a property
> // on the Person model.
> class Person: Object {
>     @Persisted var firstName = ""
>     @Persisted var lastName = ""
>     // Add a new "email" property.
>     @Persisted var email: String?
>     // New properties can be migrated
>     // automatically, but must update the schema version.
>     @Persisted var age = 0
>
> }
>
> ```
>
>
> Realm automatically migrates the realm to conform to
the updated `Person` schema. But the developer must set the realm's
schema version to `2`.
>
> #### Objective-C
>
> ```objectivec
> // When you open the realm, specify that the schema
> // is now using a newer version.
> RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
> // Set the new schema version
> config.schemaVersion = 2;
> // Use this configuration when opening realms
> [RLMRealmConfiguration setDefaultConfiguration:config];
> RLMRealm *realm = [RLMRealm defaultRealm];
>
> ```
>
>
> #### Swift
>
> ```swift
> // When you open the realm, specify that the schema
> // is now using a newer version.
> let config = Realm.Configuration(
>     schemaVersion: 2)
> // Use this configuration when opening realms
> Realm.Configuration.defaultConfiguration = config
> let realm = try! Realm()
>
> ```
>
>

### Delete a Property
To delete a property from a schema, remove the property from the object's class
and set a `schemaVersion` of the realm's configuration object. Deleting a property
will not impact existing objects.

> Example:
> A realm using schema version `1` has a `Person` object type
that has first name, last name, and age properties:
>
> #### Objective-C
>
> ```objectivec
> // In the first version of the app, the Person model
> // has separate fields for first and last names,
> // and an age property.
> @interface Person : RLMObject
> @property NSString *firstName;
> @property NSString *lastName;
> @property int age;
> @end
>
> @implementation Person
> + (NSArray<NSString *> *)requiredProperties {
>     return @[@"firstName", @"lastName", @"age"];
> }
> @end
>
> ```
>
>
> #### Swift
>
> ```swift
> // In the first version of the app, the Person model
> // has separate fields for first and last names,
> // and an age property.
> class Person: Object {
>     @Persisted var firstName = ""
>     @Persisted var lastName = ""
>     @Persisted var age = 0
> }
>
> ```
>
>
> The developer decides that the `Person` does not need the `age` field and updates the schema.
>
> #### Objective-C
>
> ```objectivec
> // In a new version, you remove a property
> // on the Person model.
> @interface Person : RLMObject
> @property NSString *firstName;
> @property NSString *lastName;
> // Remove the "age" property.
> // @property int age;
> // Removed properties can be migrated
> // automatically, but must update the schema version.
> @end
>
> @implementation Person
> + (NSArray<NSString *> *)requiredProperties {
>     return @[@"firstName", @"lastName"];
> }
> @end
>
> ```
>
>
> #### Swift
>
> ```swift
> // In a new version, you remove a property
> // on the Person model.
> class Person: Object {
>     @Persisted var firstName = ""
>     @Persisted var lastName = ""
>     // Remove the "age" property.
>     // @Persisted var age = 0
>     // Removed properties can be migrated
>     // automatically, but must update the schema version.
>
> }
>
> ```
>
>
> Realm automatically migrates the realm to conform to
the updated `Person` schema. But the developer must set the realm's
schema version to `2`.
>
> #### Objective-C
>
> ```objectivec
> // When you open the realm, specify that the schema
> // is now using a newer version.
> RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
> // Set the new schema version
> config.schemaVersion = 2;
> // Use this configuration when opening realms
> [RLMRealmConfiguration setDefaultConfiguration:config];
> RLMRealm *realm = [RLMRealm defaultRealm];
>
> ```
>
>
> #### Swift
>
> ```swift
> // When you open the realm, specify that the schema
> // is now using a newer version.
> let config = Realm.Configuration(
>     schemaVersion: 2)
> // Use this configuration when opening realms
> Realm.Configuration.defaultConfiguration = config
> let realm = try! Realm()
>
> ```
>
>

> Tip:
> SwiftUI developers may see an error that a migration is required when they
add or delete properties. This is related to the lifecycle in SwiftUI.
The Views are laid out, and then the `.environment` modifier sets the
config.
>
> To resolve a migration error in these circumstances, pass
`Realm.Configuration(schemaVersion: <Your Incremented Version>)`
into the `ObservedResults` constructor.
>

## Manually Migrate Schema
For more complex schema updates, Realm requires a manual
migration for old instances of a given object to the new schema.

### Rename a Property
To rename a property during a migration, use the
`Migration.renameProperty(onType:from:to:)`
method.

Realm applies any new nullability or indexing settings
during the rename operation.

> Example:
> Rename `age` to `yearsSinceBirth` within a `migrationBlock`.
>
> #### Objective-C
>
> ```objectivec
> RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
> config.schemaVersion = 2;
> config.migrationBlock = ^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
>     if (oldSchemaVersion < 2) {
>         // Rename the "age" property to "yearsSinceBirth".
>         // The renaming operation should be done outside of calls to `enumerateObjects(ofType: _:)`.
>         [migration renamePropertyForClass:[Person className] oldName:@"age" newName:@"yearsSinceBirth"];
>     }
> };
>
> ```
>
>
> #### Swift
>
> ```swift
> let config = Realm.Configuration(
>     schemaVersion: 2,
>     migrationBlock: { migration, oldSchemaVersion in
>         if oldSchemaVersion < 2 {
>             // Rename the "age" property to "yearsSinceBirth".
>             // The renaming operation should be done outside of calls to `enumerateObjects(ofType: _:)`.
>             migration.renameProperty(onType: Person.className(), from: "age", to: "yearsSinceBirth")
>         }
>     })
>
> ```
>
>

### Modify Properties
> Tip:
> You can use the `deleteRealmIfMigrationNeeded`
method to delete the realm if it would require a migration. This can
be useful during development when you need to iterate quickly and don't
want to perform the migration.
>

To define custom migration logic, set the `migrationBlock`
property of the `Configuration` when opening a realm.

The migration block receives a `Migration object` that you can use to perform the migration. You
can use the Migration object's `enumerateObjects(ofType:_:)`
method to iterate over and update all instances of a given
Realm type in the realm.

> Example:
> A realm using schema version `1` has a `Person` object type
that has separate fields for first and last names:
>
> #### Objective-C
>
> ```objectivec
> // In the first version of the app, the Person model
> // has separate fields for first and last names,
> // and an age property.
> @interface Person : RLMObject
> @property NSString *firstName;
> @property NSString *lastName;
> @property int age;
> @end
>
> @implementation Person
> + (NSArray<NSString *> *)requiredProperties {
>     return @[@"firstName", @"lastName", @"age"];
> }
> @end
>
> ```
>
>
> #### Swift
>
> ```swift
> // In the first version of the app, the Person model
> // has separate fields for first and last names,
> // and an age property.
> class Person: Object {
>     @Persisted var firstName = ""
>     @Persisted var lastName = ""
>     @Persisted var age = 0
> }
>
> ```
>
>
> The developer decides that the `Person` class should use a combined
`fullName` field instead of the separate `firstName` and
`lastName` fields and updates the schema.
>
> To migrate the realm to conform to the updated `Person` schema,
the developer sets the realm's schema version to `2` and
defines a migration function to set the value of `fullName` based
on the existing `firstName` and `lastName` properties.
>
> #### Objective-C
>
> ```objectivec
> // In version 2, the Person model has one
> // combined field for the full name and age as a Int.
> // A manual migration will be required to convert from
> // version 1 to this version.
> @interface Person : RLMObject
> @property NSString *fullName;
> @property int age;
> @end
>
> @implementation Person
> + (NSArray<NSString *> *)requiredProperties {
>     return @[@"fullName", @"age"];
> }
> @end
>
> ```
>
> ```objectivec
> RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
> // Set the new schema version
> config.schemaVersion = 2;
> config.migrationBlock = ^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
>     if (oldSchemaVersion < 2) {
>         // Iterate over every 'Person' object stored in the Realm file to
>         // apply the migration
>         [migration enumerateObjects:[Person className]
>                             block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
>             // Combine name fields into a single field
>             newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
>                                         oldObject[@"firstName"],
>                                         oldObject[@"lastName"]];
>         }];
>     }
> };
>
> // Tell Realm to use this new configuration object for the default Realm
> [RLMRealmConfiguration setDefaultConfiguration:config];
>
> // Now that we've told Realm how to handle the schema change, opening the realm
> // will automatically perform the migration
> RLMRealm *realm = [RLMRealm defaultRealm];
>
> ```
>
>
> #### Swift
>
> ```swift
> // In version 2, the Person model has one
> // combined field for the full name and age as a Int.
> // A manual migration will be required to convert from
> // version 1 to this version.
> class Person: Object {
>     @Persisted var fullName = ""
>     @Persisted var age = 0
> }
>
> ```
>
> ```swift
> // In application(_:didFinishLaunchingWithOptions:)
> let config = Realm.Configuration(
>     schemaVersion: 2, // Set the new schema version.
>     migrationBlock: { migration, oldSchemaVersion in
>         if oldSchemaVersion < 2 {
>             // The enumerateObjects(ofType:_:) method iterates over
>             // every Person object stored in the Realm file to apply the migration
>             migration.enumerateObjects(ofType: Person.className()) { oldObject, newObject in
>                 // combine name fields into a single field
>                 let firstName = oldObject!["firstName"] as? String
>                 let lastName = oldObject!["lastName"] as? String
>                 newObject!["fullName"] = "\(firstName!) \(lastName!)"
>             }
>         }
>     }
> )
>
> // Tell Realm to use this new configuration object for the default Realm
> Realm.Configuration.defaultConfiguration = config
>
> // Now that we've told Realm how to handle the schema change, opening the file
> // will automatically perform the migration
> let realm = try! Realm()
>
> ```
>
>
> Later, the developer decides that the `age` field should be of type `String`
rather than `Int` and updates the schema.
>
> To migrate the realm to conform to the updated `Person` schema,
the developer sets the realm's schema version to `3` and
adds a conditional to the migration function so that the function defines
how to migrate from any previous version to the new one.
>
> #### Objective-C
>
> ```objectivec
> // In version 3, the Person model has one
> // combined field for the full name and age as a String.
> // A manual migration will be required to convert from
> // version 2 to this version.
> @interface Person : RLMObject
> @property NSString *fullName;
> @property NSString *age;
> @end
>
> @implementation Person
> + (NSArray<NSString *> *)requiredProperties {
>     return @[@"fullName", @"age"];
> }
> @end
>
> ```
>
> ```objectivec
> RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
> // Set the new schema version
> config.schemaVersion = 3;
> config.migrationBlock = ^(RLMMigration * _Nonnull migration, uint64_t oldSchemaVersion) {
>     if (oldSchemaVersion < 2) {
>         // Previous Migration.
>         [migration enumerateObjects:[Person className]
>                             block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
>             newObject[@"fullName"] = [NSString stringWithFormat:@"%@ %@",
>                                         oldObject[@"firstName"],
>                                         oldObject[@"lastName"]];
>         }];
>     }
>     if (oldSchemaVersion < 3) {
>         // New Migration
>         [migration enumerateObjects:[Person className]
>                             block:^(RLMObject * _Nullable oldObject, RLMObject * _Nullable newObject) {
>             // Make age a String instead of an Int
>             newObject[@"age"] = [oldObject[@"age"] stringValue];
>         }];
>     }
> };
>
> // Tell Realm to use this new configuration object for the default Realm
> [RLMRealmConfiguration setDefaultConfiguration:config];
>
> // Now that we've told Realm how to handle the schema change, opening the realm
> // will automatically perform the migration
> RLMRealm *realm = [RLMRealm defaultRealm];
>
> ```
>
>
> #### Swift
>
> ```swift
> // In version 3, the Person model has one
> // combined field for the full name and age as a String.
> // A manual migration will be required to convert from
> // version 2 to this version.
>  class Person: Object {
>     @Persisted var fullName = ""
>     @Persisted var age = "0"
>  }
>
> ```
>
> ```swift
> // In application(_:didFinishLaunchingWithOptions:)
> let config = Realm.Configuration(
>     schemaVersion: 3, // Set the new schema version.
>     migrationBlock: { migration, oldSchemaVersion in
>         if oldSchemaVersion < 2 {
>             // Previous Migration.
>             migration.enumerateObjects(ofType: Person.className()) { oldObject, newObject in
>                 let firstName = oldObject!["firstName"] as? String
>                 let lastName = oldObject!["lastName"] as? String
>                 newObject!["fullName"] = "\(firstName!) \(lastName!)"
>             }
>         }
>         if oldSchemaVersion < 3 {
>             // New Migration.
>             migration.enumerateObjects(ofType: Person.className()) { oldObject, newObject in
>                 // Make age a String instead of an Int
>                 newObject!["age"] = "\(oldObject!["age"] ?? 0)"
>             }
>         }
>     }
> )
>
> // Tell Realm to use this new configuration object for the default Realm
> Realm.Configuration.defaultConfiguration = config
>
> // Now that we've told Realm how to handle the schema change, opening the file
> // will automatically perform the migration
> let realm = try! Realm()
>
> ```
>
>

> Tip:
> Avoid nesting or otherwise skipping `if (oldSchemaVersion < X)` statements
in migration blocks. This ensures that all updates can be applied in the correct order,
no matter which schema version a client starts from. The goal is to define
migration logic which can transform data from any outdated schema version to
match the current schema.
>

### Convert from Object to EmbeddedObject
Embedded objects cannot exist
independently of a parent object. When changing an Object to an
EmbeddedObject, the migration block must ensure that every embedded
object has exactly one backlink to a parent object. Having no backlinks
or multiple backlinks raises the following exceptions:

```
At least one object does not have a backlink (data would get lost).
```

```
At least one object does have multiple backlinks.
```

> Seealso:
> Define an Embedded Object Property
>

## Additional Migration Examples
Please check out the additional migration examples on the
[realm-swift repo](https://github.com/realm/realm-swift/tree/master/examples/ios/swift/Migration).

---

### Guides Model Data Model Data (`docs/guides/model-data/model-data.md`)

# Model Data - Swift SDK
## Object Types & Schemas
Realm applications model data as objects composed of
field-value pairs that each contain one or more supported data types.

Realm objects are regular Swift or Objective-C classes, but
they also bring a few additional features like live queries. The Swift SDK memory maps Realm objects directly to
native Swift or Objective-C objects, which means there's no need to use
a special data access library, such as an [ORM](https://en.wikipedia.org/wiki/Object-relational_mapping). Instead, you can work with Realm objects
as you would any other class instance.

Every Realm object conforms to a specific **object type**, which is
essentially a class that defines the properties
and relationships for objects of that type.
Realm guarantees that all objects in a realm conform to
the schema for their object type and validates objects whenever they're
created, modified, or deleted.

> Example:
> The following schema defines a `Dog` object type with a string name,
optional string breed, date of birth, and primary key ID.
>
> #### Objective-C
>
> ```objectivec
> // A dog has an _id primary key, a string name, an optional
> // string breed, and a date of birth.
> @interface Dog : RLMObject
> @property RLMObjectId *_id;
> @property NSString *name;
> @property NSString *breed;
> @property NSDate *dateOfBirth;
> @end
>
> @implementation Dog
> + (NSString *)primaryKey {
>     return @"_id";
> }
>
> + (NSArray<NSString *> *)requiredProperties {
>     return @[
>         @"_id", @"name", @"dateOfBirth"
>     ];
> }
> @end
>
> ```
>
>
> #### Swift
>
> ```swift
> // A dog has an _id primary key, a string name, an optional
> // string breed, and a date of birth.
> class Dog: Object {
>     @Persisted(primaryKey: true) var _id: ObjectId
>     @Persisted var name = ""
>     @Persisted var breed: String?
>     @Persisted var dateOfBirth = Date()
> }
>
> ```
>
>

### Realm Schema
A **realm schema** is a list of valid object schemas that a realm may contain. Every Realm object must
conform to an object type that's included in its realm's schema.

By default, the Swift SDK automatically adds all classes in your project
that derive from [RLMObject](https://www.mongodb.com/docs/realm-sdks/objc/latest/Classes/RLMObject.html) or
[RLMEmbeddedObject](https://www.mongodb.com/docs/realm-sdks/objc/latest/Classes/RLMEmbeddedObject.html) to the
realm schema.

> Tip:
> To control which classes Realm adds to a realm schema, see
Provide a Subset of Classes to a Realm.
>

If a realm already contains data when you open it,
Realm validates each object to ensure that an object
schema was provided for its type and that it meets all of the
constraints specified in the schema.

> Tip:
> For code examples that show how to configure and open a realm in the
Swift SDK, see Configure & Open a Realm - Swift SDK.
>

### Model Inheritance
You can subclass Realm models to share behavior between
classes, but there are limitations. In particular, Realm
does not allow you to:

- Cast between polymorphic classes: subclass to subclass, subclass to parent, parent to subclass
- Query on multiple classes simultaneously: for example, "get all instances of parent class and subclass"
- Multi-class containers: `List` and `Results` with a mixture of parent and subclass

> Tip:
> Check out the [code samples](https://github.com/realm/realm-swift/issues/1109#issuecomment-143834756) for working
around these limitations.
>

> Version added: 10.10.0While you can't mix  and  property declarations
within a class, you can mix the notation styles across base and subclasses.
For example, a base class could have a  property,
and a subclass could have an  property, with
both persisted. However, the  property would be ignored if
the  property were within the same base or subclass.

### Swift Structs
Realm does not support Swift structs as models for a variety of
reasons. Realm's design focuses on "live" objects.
This concept is not compatible with value type structs. By design,
Realm provides features that are incompatible with these
semantics, such as:

- Live data
- Reactive APIs
- Low memory footprint of data
- Good operation performance
- Lazy and cheap access to partial data
- Lack of data serialization/deserialization
- Keeping potentially complex object graphs synchronized

That said, it is sometimes useful to detach objects from their backing
realm. This typically isn't an ideal design decision. Instead,
developers use this as a workaround for temporary limitations in our
library.

You can use key-value coding to initialize an unmanaged object as a copy of
a managed object. Then, you can work with that unmanaged object
like any other [NSObject](https://developer.apple.com/documentation/objectivec/nsobject).

```swift
let standaloneModelObject = MyModel(value: persistedModelObject)
```

## Properties
Your Realm object model is a collection of properties. On the most basic level,
when you create your model, your declarations give Realm information about
each property:

- The data type and whether the property is optional or required
- Whether Realm should store or ignore the property
- Whether the property is a primary key or should be indexed

Properties are also the mechanism for establishing relationships between Realm object types.

The Realm Swift SDK uses reflection to determine the properties
in your models at runtime. Your project must not set
`SWIFT_REFLECTION_METADATA_LEVEL = none`, or Realm cannot discover
children of types, such as properties and enum cases. Reflection is enabled
by default if your project does not specifically set a level for this setting.

## View Models with Realm
> Version added: 10.21.0

You can work with a subset of your Realm object's properties
by creating a class projection. A class projection is a class that passes
through or transforms some or all of your Realm object's
properties. Class projection enables you to build view models that use an
abstraction of your object model. This simplifies using and testing Realm objects
in your application.

With class projection, you can use a subset of your object's properties
directly in the UI or transform them. When you use a class projection for
this, you get all the benefits of Realm's live objects:

- The class-projected object live updates
- You can observe it for changes
- You can apply changes directly to the properties in write transactions

> Seealso:
> Define a Class Projection
>

## Relationships
Realm doesn't use bridge tables or explicit joins to define
relationships as you would in a relational database. Realm
handles relationships through embedded objects or reference properties to
other Realm objects. You read from and write to these
properties directly. This makes querying relationships as performant as
querying against any other property.

Realm supports **to-one**, **to-many**, and **inverse**
relationships.

### To-One Relationship
A **to-one** relationship means that an object relates to one other object.
You define a to-one relationship for an object type in its object
schema. Specify a property where the type is the related Realm
object type. For example, a dog might have a to-one relationship with
a favorite toy.

> Tip:
> To learn how to define a to-one relationship, see
Define a To-One Relationship Property.
>

### To-Many Relationship
A **to-many** relationship means that an object relates to more than one
other object. In Realm, a to-many relationship is a list of
references to other objects. For example, a person might have many dogs.

A `List` represents the to-many
relationship between two Realm
types. Lists are mutable: within a write transaction, you can add and
remove elements to and from a list. Lists are not associated with a
query and are usually declared as a property of an object model.

> Tip:
> To learn how to define a to-many relationship, see
Define a To-Many Relationship Property.
>

### Inverse Relationship
Relationship definitions in Realm are unidirectional. An
**inverse relationship** links an object back to an object that refers
to it. You must explicitly define a property in the object's model as an
inverse relationship. Inverse relationships can link back to objects in
a to-one or to-many relationship.

A `LinkingObjects` collection
represents the inverse relationship
between two Realm types. You cannot directly add or remove
items from a LinkingObjects collection.

Inverse relationships automatically update themselves with corresponding
backlinks. You can find the same set of Realm objects with a
manual query, but the inverse relationship field reduces boilerplate query
code and capacity for error.

For example, consider a task tracker with the to-many relationship "User has
many Tasks". This does not automatically create the inverse relationship
"Task belongs to User". To create the inverse relationship, add a User
property on the Task that points back to the task's owner. When you specify
the inverse relationship from task to user, you can query on that. If you
don't specify the inverse relationship, you must run a separate query to
look up the user to whom the task is assigned.

> Important:
> You cannot manually set the value of an inverse relationship property.
Instead, Realm updates implicit relationships when you add
or remove an object in the relationship.
>

Relationships can be many-to-one or many-to-many. So following inverse
relationships can result in zero, one, or many objects.

> Tip:
> To learn how to define an inverse relationship, see
Define an Inverse Relationship Property.
>

---

### Guides Model Data Object Models (`docs/guides/model-data/object-models.md`)

# Define a Realm Object Model - Swift SDK
## Define a New Object Type
#### Objective-C

You can define a Realm object by deriving from the
`RLMObject` or
`RLMEmbeddedObject` class. The name of the
class becomes the table name in the realm, and properties of the
class persist in the database. This makes it as easy to work with
persisted objects as it is to work with regular Objective-C
objects.

```objectivec
// A dog has an _id primary key, a string name, an optional
// string breed, and a date of birth.
@interface Dog : RLMObject
@property RLMObjectId *_id;
@property NSString *name;
@property NSString *breed;
@property NSDate *dateOfBirth;
@end

@implementation Dog
+ (NSString *)primaryKey {
    return @"_id";
}

+ (NSArray<NSString *> *)requiredProperties {
    return @[
        @"_id", @"name", @"dateOfBirth"
    ];
}
@end

```

#### Swift

You can define a Realm object by deriving from the
`Object` or
`EmbeddedObject`
class. The name of the class becomes the table name in the realm,
and properties of the class persist in the database. This makes it
as easy to work with persisted objects as it is to work with
regular Swift objects.

```swift
// A dog has an _id primary key, a string name, an optional
// string breed, and a date of birth.
class Dog: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var name = ""
    @Persisted var breed: String?
    @Persisted var dateOfBirth = Date()
}

```

> Note:
> Class names are limited to a maximum of 57 UTF-8 characters.
>

## Declare Properties
When you declare the property attributes of a class, you can specify whether
or not those properties should be managed by the realm. **Managed properties**
are stored or updated in the database. **Ignored properties** are not
stored to the database. You can mix managed and ignored properties
within a class.

The syntax to mark properties as managed or ignored varies depending on which
version of the SDK you use.

### Persisted Property Attributes
> Version added: 10.10.0The  declaration style replaces the ,
, and  declaration notations from older
versions of the SDK. For an older version of the SDK, see:
.

Declare model properties that you want to store to the database as
`@Persisted`. This enables them to access the underlying database data.

When you declare any properties as `@Persisted` within a class, the other
properties within that class are automatically ignored.

If you mix `@Persisted` and `@objc dynamic` property declarations within
a class definition, any property attributes marked as `@objc dynamic` will
be ignored.

> Seealso:
> Our Supported Property Types
page contains a property declaration cheatsheet.
>

### Objective-C Dynamic Property Attributes
> Version changed: 10.10.0This property declaration information is for versions of the SDK before
10.10.0.

Declare dynamic Realm model properties in the Objective-C runtime. This
enables them to access the underlying database data.

You can either:

- Use `@objc dynamic var` to declare individual properties
- Use `@objcMembers` to declare a class. Then, declare individual
properties with `dynamic var`.

Use `let` to declare `LinkingObjects`, `List`, `RealmOptional` and
`RealmProperty`. The Objective-C runtime cannot represent these
generic properties.

> Version changed: 10.8.0
> `RealmProperty` replaces `RealmOptional`
>

> Seealso:
> Our Supported Property Types
page contains a property declaration cheatsheet.
>

> Tip:
> For reference on which types Realm supports for use as
properties, see Supported Property Types.
>

#### Swift

When declaring non-generic properties, use the `@Persisted` annotation.
The `@Persisted` attribute turns Realm model properties into accessors
for the underlying database data.

#### Objective-C

Declare properties on your object type as you would on a normal
Objective-C interface.

In order to use your interface in a Realm array, pass your
interface name to the `RLM_COLLECTION_TYPE()` macro. You can put this
at the bottom of your interface's header file. The
`RLM_COLLECTION_TYPE()` macro creates a protocol that allows you to
tag `RLMArray` with your type:

```objectivec
// Task.h
@interface Task : RLMObject
@property NSString *description;
@end

// Define an RLMArray<Task> type
RLM_COLLECTION_TYPE(Task)

// User.h
// #include "Task.h"
@interface User : RLMObject
@property NSString *name;
// Use RLMArray<Task> to have a list of tasks
// Note the required double tag (<Task *><Task>)
@property RLMArray<Task *><Task> *tasks;
@end

```

#### Swift Pre 10.10.0

When declaring non-generic properties, use the `@objc dynamic
var` annotation. The `@objc dynamic var` attribute turns Realm
model properties into accessors for the underlying database data.
If the class is declared as `@objcMembers` (Swift 4 or later),
you can declare properties as `dynamic var` without `@objc`.

To declare properties of generic types `LinkingObjects`,
`List`, and `RealmProperty`, use `let`. Generic properties
cannot be represented in the Objective‑C runtime, which
Realm uses for dynamic dispatch of dynamic
properties.

> Note:
> Property names are limited to a maximum of 63 UTF-8 characters.
>

### Specify an Optional/Required Property
#### Swift

You can declare properties as optional or required (non-optional) using
standard Swift syntax.

```swift
class Person: Object {
    // Required string property
    @Persisted var name = ""

    // Optional string property
    @Persisted var address: String?

    // Required numeric property
    @Persisted var ageYears = 0

    // Optional numeric property
    @Persisted var heightCm: Float?
}

```

#### Objective-C

To declare a given property as required, implement the
`requiredProperties`
method and return an array of required property names.

```objectivec
@interface Person : RLMObject
// Required property - included in `requiredProperties`
// return value array
@property NSString *name;

// Optional string property - not included in `requiredProperties`
@property NSString *address;

// Required numeric property
@property int ageYears;

// Optional numeric properties use NSNumber tagged
// with RLMInt, RLMFloat, etc.
@property NSNumber<RLMFloat> *heightCm;
@end

@implementation Person
// Specify required pointer-type properties here.
// Implicitly required properties (such as properties
// of primitive types) do not need to be named here.
+ (NSArray<NSString *> *)requiredProperties {
    return @[@"name"];
}
@end

```

#### Swift Pre 10.10.0

> Version changed: 10.8.0
> `RealmProperty` replaces `RealmOptional`
>

You can declare `String`, `Date`, `Data`, and
`ObjectId` properties as
optional or required (non-optional) using standard Swift syntax.
Declare optional numeric types using the `RealmProperty`
type.

```swift
class Person: Object {
    // Required string property
    @objc dynamic var name = ""

    // Optional string property
    @objc dynamic var address: String?

    // Required numeric property
    @objc dynamic var ageYears = 0

    // Optional numeric property
    let heightCm = RealmProperty<Float?>()
}

```

RealmProperty supports `Int`, `Float`, `Double`, `Bool`,
and all of the sized versions of `Int` (`Int8`, `Int16`,
`Int32`, `Int64`).

### Specify a Primary Key
You can designate a property as the **primary key** of your class.

Primary keys allow you to efficiently find, update, and upsert objects.

Primary keys are subject to the following limitations:

- You can define only one primary key per object model.
- Primary key values must be unique across all instances of an object
in a realm. Realm throws an error if you try to
insert a duplicate primary key value.
- Primary key values are immutable. To change the primary key value of
an object, you must delete the original object and insert a new object
with a different primary key value.
- Embedded objects cannot define a
primary key.

#### Swift

Declare the property with `primaryKey: true`
on the `@Persisted` notation to set the model's primary key.

```swift
class Project: Object {
    @Persisted(primaryKey: true) var id = 0
    @Persisted var name = ""
}

```

#### Objective-C

Override `+[RLMObject primaryKey]` to
set the model's primary key.

```objectivec
@interface Project : RLMObject
@property NSInteger id; // Intended primary key
@property NSString *name;
@end

@implementation Project
// Return the name of the primary key property
+ (NSString *)primaryKey {
    return @"id";
}
@end

```

#### Swift Pre 10.10.0

Override `Object.primaryKey()`
to set the model's primary key.

```swift
class Project: Object {
    @objc dynamic var id = 0
    @objc dynamic var name = ""

    // Return the name of the primary key property
    override static func primaryKey() -> String? {
        return "id"
    }
}

```

### Index a Property
You can create an index on a given property of your model. Indexes speed up
queries using equality and IN operators. They make insert and update operation
speed slightly slower. Indexes use memory and take up more space in the realm
file. Each index entry is a minimum of 12 bytes. It's best to only add indexes
when optimizing the read performance for specific situations.

Realm supports indexing for string, integer, boolean, `Date`, `UUID`,
`ObjectId`, and `AnyRealmValue` properties.

> Version added: 10.8.0
> `UUID` and `AnyRealmValue` types
>

#### Swift

To index a property, declare the property with
`indexed:true`
on the `@Persisted` notation.

```swift
class Book: Object {
    @Persisted var priceCents = 0
    @Persisted(indexed: true) var title = ""
}

```

#### Objective-C

To index a property, override `RLMObject
indexedProperties`
and return a list of indexed property names.

```objectivec
@interface Book : RLMObject
@property int priceCents;
@property NSString *title;
@end

@implementation Book
// Return a list of indexed property names
+ (NSArray *)indexedProperties {
    return @[@"title"];
}
@end

```

#### Swift Pre 10.10.0

To index a property, override
`Object.indexedProperties()`
and return a list of indexed property names.

```swift
class Book: Object {
    @objc dynamic var priceCents = 0
    @objc dynamic var title = ""

    // Return a list of indexed property names
    override static func indexedProperties() -> [String] {
        return ["title"]
    }
}

```

### Ignore a Property
Ignored properties behave exactly like normal properties. They can't be
used in queries and won't trigger Realm notifications. You can still
observe them using [KVO](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/KeyValueObserving/KeyValueObserving.html).

> Tip:
> Realm automatically ignores read-only properties.
>

#### Swift

> Deprecated:

If you don't want to save a field in your model to its realm,
leave the `@Persisted` notation off the property attribute.

Additionally, if you mix `@Persisted` and `@objc dynamic`
property declarations within a class, the `@objc dynamic`
properties will be ignored.

```swift
class Person: Object {
    // If some properties are marked as @Persisted,
    // any properties that do not have the @Persisted
    // annotation are automatically ignored.
    var tmpId = 0

    // The @Persisted properties are managed
    @Persisted var firstName = ""
    @Persisted var lastName = ""

    // Read-only properties are automatically ignored
    var name: String {
        return "\(firstName) \(lastName)"
    }

    // If you mix the pre-10.10 property declaration
    // syntax `@objc dynamic` with the 10.10+ @Persisted
    // annotation within a class, `@objc dynamic`
    // properties are ignored.
    @objc dynamic var email = ""
}

```

#### Objective-C

If you don't want to save a field in your model to its realm,
override `+[RLMObject ignoredProperties]`
and return a list of ignored property names.

```objectivec
@interface Person : RLMObject
@property NSInteger tmpId;
@property (readonly) NSString *name; // read-only properties are automatically ignored
@property NSString *firstName;
@property NSString *lastName;
@end

@implementation Person
+ (NSArray *)ignoredProperties {
    return @[@"tmpId"];
}
- (NSString *)name {
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}
@end

```

#### Swift Pre 10.10.0

If you don't want to save a field in your model to its realm,
override `Object.ignoredProperties()`
and return a list of ignored property names.

```swift
class Person: Object {
    @objc dynamic var tmpId = 0
    @objc dynamic var firstName = ""
    @objc dynamic var lastName = ""

    // Read-only properties are automatically ignored
    var name: String {
        return "\(firstName) \(lastName)"
    }

    // Return a list of ignored property names
    override static func ignoredProperties() -> [String] {
        return ["tmpId"]
    }
}

```

### Declare Enum Properties
#### Swift

> Version changed: 10.10.0
> Protocol is now `PersistableEnum` rather than `RealmEnum`.
>

You can use enums with `@Persisted` by marking them as complying with the
`PersistableEnum`
protocol. A `PersistableEnum` can be any `RawRepresentable` enum
whose raw type is a type that Realm supports.

```swift
// Define the enum
enum TaskStatusEnum: String, PersistableEnum {
    case notStarted
    case inProgress
    case complete
}

// To use the enum:
class Task: Object {
    @Persisted var name: String = ""
    @Persisted var owner: String?

    // Required enum property
    @Persisted var status = TaskStatusEnum.notStarted

    // Optional enum property
    @Persisted var optionalTaskStatusEnumProperty: TaskStatusEnum?
}

```

#### Swift Pre 10.10.0

Realm supports only `Int`-backed `@objc` enums.

```swift
// Define the enum
@objc enum TaskStatusEnum: Int, RealmEnum {
    case notStarted = 1
    case inProgress = 2
    case complete = 3
}

// To use the enum:
class Task: Object {
    @objc dynamic var name: String = ""
    @objc dynamic var owner: String?

    // Required enum property
    @objc dynamic var status = TaskStatusEnum.notStarted
    // Optional enum property
    let optionalTaskStatusEnumProperty = RealmProperty<TaskStatusEnum?>()
}

```

> Seealso:
> `RealmEnum`
>

### Remap a Property Name
> Version added: 10.33.0

You can map the public name of a property in your object model to a different
private name to store in the realm.

Declare the name you want to use in your project as the `@Persisted`
property on the object model. Then, pass a dictionary containing the
public and private values for the property names via the
`propertiesMapping()` function.

In this example, `firstName` is the public property name we use in the code
throughout the project to perform CRUD operations. Using the `propertiesMapping()`
function, we map that to store values using the private property name
`first_name` in the realm.

```swift
class Person: Object {
    @Persisted var firstName = ""
    @Persisted var lastName = ""

    override class public func propertiesMapping() -> [String: String] {
        ["firstName": "first_name",
         "lastName": "last_name"]
    }
}

```

## Define a Class Projection
### About These Examples
The examples in this section use a simple data set. The two Realm object
types are `Person` and an embedded object `Address`. A `Person` has
a first and last name, an optional `Address`, and a list of friends
consisting of other `Person` objects. An `Address` has a city and country.

See the schema for these two classes, `Person` and `Address`, below:

```swift
class Person: Object {
    @Persisted var firstName = ""
    @Persisted var lastName = ""
    @Persisted var address: Address?
    @Persisted var friends = List<Person>()
}

class Address: EmbeddedObject {
    @Persisted var city: String = ""
    @Persisted var country = ""
}

```

### How to Define a Class Projection
> Version added: 10.21.0

Define a class projection by creating a class of type `Projection`. Specify the `Object`
or `EmbeddedObject` base whose
properties you want to use in the class projection. Use the `@Projected`
property wrapper to declare a property that you want to project from a
`@Persisted` property on the base object.

> Note:
> When you use a List or a MutableSet in a class projection, the type in the
class projection should be `ProjectedCollection`.
>

```swift
class PersonProjection: Projection<Person> {
    @Projected(\Person.firstName) var firstName // Passthrough from original object
    @Projected(\Person.address?.city) var homeCity // Rename and access embedded object property through keypath
    @Projected(\Person.friends.projectTo.firstName) var firstFriendsName: ProjectedCollection<String> // Collection mapping
}

```

When you define a class projection, you can transform the original `@Persisted`
property in several ways:

- Passthrough: the property is the same name and type as the original object
- Rename: the property has the same type as the original object, but a
different name
- Keypath resolution: use keypath resolution to access properties of the
original object, including embedded object properties
- Collection mapping: Project lists or
mutable sets of `Object` s or
`EmbeddedObject` s as a collection of primitive values
- Exclusion: when you use a class projection, the underlying object's
properties that are not `@Projected` through the class projection are
excluded. This enables you to watch for changes to a class projection
and not see changes for properties that are not part of the class
projection.

## Define Unstructured Data
> Version added: 10.51.0

Starting in SDK version 10.51.0, you can store collections of mixed data
within a `AnyRealmValue` property. You can use this feature to model complex data
structures, such as JSON, without having to define a
strict data model.

**Unstructured data** is data that doesn't easily conform to an expected
schema, making it difficult or impractical to model to individual
data classes. For example, your app might have highly variable data or dynamic
data whose structure is unknown at runtime.

Storing collections in a mixed property offers flexibility without sacrificing
functionality. And
you can work with them the same way you would a non-mixed
collection:

- You can nest mixed collections up to 100 levels.
- You can query on and react to changes on mixed collections.
- You can find and update individual mixed collection elements.

However, storing data in mixed collections is less performant than using a structured
schema or serializing JSON blobs into a single string property.

To model unstructured data in your app, define the appropriate properties in
your schema as AnyRealmValue types. You can then
set these `AnyRealmValue` properties as a list or a
dictionary collection of `AnyRealmValue` elements.
Note that `AnyRealmValue` *cannot* represent a `MutableSet` or an embedded
object.

> Tip:
> - Use a map of mixed data types when the type is unknown but each value will have a unique identifier.
> - Use a list of mixed data types when the type is unknown but the order of
objects is meaningful.
>

---

### Guides Model Data Relationships (`docs/guides/model-data/relationships.md`)

# Model Relationships - Swift SDK
## Declare Relationship Properties

### Define a To-One Relationship Property
A **to-one** relationship maps one property to a single instance of
another object type. For example, you can model a person having at most
one companion dog as a to-one relationship.

Setting a relationship field to null removes the connection between objects.
Realm does not delete the referenced object, though, unless it is
an embedded object.

> Important:
> When you declare a to-one relationship in your object model, it must
be an optional property. If you try to make a to-one relationship
required, Realm throws an exception at runtime.
>

#### Objective-C

```objectivec
// Dog.h
@interface Dog : RLMObject
@property NSString *name;
// No backlink to person -- one-directional relationship
@end

// Define an RLMArray<Dog> type
RLM_COLLECTION_TYPE(Dog)

// Person.h
@interface Person : RLMObject
@property NSString *name;
// A person can have one dog
@property Dog *dog;
@end

// Dog.m
@implementation Dog
@end

// Person.m
@implementation Person
@end

```

#### Swift

```swift
class Person: Object {
    @Persisted var name: String = ""
    @Persisted var birthdate: Date = Date(timeIntervalSince1970: 1)

    // A person can have one dog
    @Persisted var dog: Dog?
}

class Dog: Object {
    @Persisted var name: String = ""
    @Persisted var age: Int = 0
    @Persisted var breed: String?
    // No backlink to person -- one-directional relationship
}

```

> Seealso:
> For more information about to-one relationships, see:
To-One Relationship.
>

### Define a To-Many Relationship Property
A **to-many** relationship maps one property to zero or more instances
of another object type. For example, you can model a person having any
number of companion dogs as a to-many relationship.

#### Objective-C

Use `RLMArray` tagged with your
target type to define your to-many relationship property.

> Tip:
> Remember to use the `RLM_COLLECTION_TYPE()` macro with your type
to declare the RLMArray protocol for your type.
>

```objectivec
// Dog.h
@interface Dog : RLMObject
@property NSString *name;
// No backlink to person -- one-directional relationship
@end

// Define an RLMArray<Dog> type
RLM_COLLECTION_TYPE(Dog)

// Person.h
@interface Person : RLMObject
@property NSString *name;
// A person can have many dogs
@property RLMArray<Dog *><Dog> *dogs;
@end

// Dog.m
@implementation Dog
@end

// Person.m
@implementation Person
@end

```

#### Swift

Use `List` tagged with your target
type to define your to-many relationship property.

```swift
class Person: Object {
    @Persisted var name: String = ""
    @Persisted var birthdate: Date = Date(timeIntervalSince1970: 1)

    // A person can have many dogs
    @Persisted var dogs: List<Dog>
}

class Dog: Object {
    @Persisted var name: String = ""
    @Persisted var age: Int = 0
    @Persisted var breed: String?
    // No backlink to person -- one-directional relationship
}

```

> Seealso:
> For more information about to-many relationships, see:
To-Many Relationship.
>

### Define an Inverse Relationship Property
An **inverse relationship** property is an automatic backlink
relationship. Realm automatically updates implicit
relationships whenever an object is added or removed in a corresponding
to-many list or to-one relationship property. You cannot manually set
the value of an inverse relationship property.

#### Swift

To define an inverse relationship, use `LinkingObjects` in your object model. The
`LinkingObjects` definition specifies the object type and
property name of the relationship that it inverts.

```swift
class User: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var _partition: String = ""
    @Persisted var name: String = ""

    // A user can have many tasks.
    @Persisted var tasks: List<Task>
}

class Task: Object {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var _partition: String = ""
    @Persisted var text: String = ""

    // Backlink to the user. This is automatically updated whenever
    // this task is added to or removed from a user's task list.
    @Persisted(originProperty: "tasks") var assignee: LinkingObjects<User>
}

```

#### Objective-C

To define an inverse relationship, use
`RLMLinkingObjects` in your object model.
Override `+[RLMObject linkingObjectProperties]`
method in your class to specify the object type and property name
of the relationship that it inverts.

```objectivec
// Task.h
@interface Task : RLMObject
@property NSString *description;
@property (readonly) RLMLinkingObjects *assignees;
@end

// Define an RLMArray<Task> type
RLM_COLLECTION_TYPE(Task)

// User.h
@interface User : RLMObject
@property NSString *name;
@property RLMArray<Task *><Task> *tasks;
@end

// Task.m
@implementation Task
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"assignees": [RLMPropertyDescriptor descriptorWithClass:User.class propertyName:@"tasks"],
    };
}
@end

// User.m
@implementation User
@end

```

#### Swift Pre 10.10.0

To define an inverse relationship, use `LinkingObjects`
in your object model. The `LinkingObjects` definition specifies
the object type and property name of the relationship that it inverts.

```swift
class User: Object {
    @objc dynamic var _id: ObjectId = ObjectId.generate()
    @objc dynamic var _partition: String = ""
    @objc dynamic var name: String = ""

    // A user can have many tasks.
    let tasks = List<Task>()

    override static func primaryKey() -> String? {
        return "_id"
    }
}

class Task: Object {
    @objc dynamic var _id: ObjectId = ObjectId.generate()
    @objc dynamic var _partition: String = ""
    @objc dynamic var text: String = ""

    // Backlink to the user. This is automatically updated whenever
    // this task is added to or removed from a user's task list.
    let assignee = LinkingObjects(fromType: User.self, property: "tasks")

    override static func primaryKey() -> String? {
        return "_id"
    }
}

```

> Seealso:
> For more information about inverse relationships, see:
Inverse Relationship.
>

### Define an Embedded Object Property
An **embedded object** exists as nested data inside of a single,
specific parent object. It inherits the lifecycle of its parent object
and cannot exist as an independent Realm object. Realm automatically
deletes embedded objects if their parent object is deleted or when
overwritten by a new embedded object instance.

> Note:
> When you delete a Realm object, any embedded objects referenced by
that object are deleted with it. If you want the referenced objects
to persist after the deletion of the parent object, your type should
not be an embedded object at all. Use a regular Realm object with a to-one relationship instead.
>

#### Objective-C

You can define an embedded object by deriving from the
`RLMEmbeddedObject` class. You can use your
embedded object in another model as you would any other type.

```objectivec
// Define an embedded object
@interface Address : RLMEmbeddedObject
@property NSString *street;
@property NSString *city;
@property NSString *country;
@property NSString *postalCode;
@end

// Enable Address for use in RLMArray
RLM_COLLECTION_TYPE(Address)

@implementation Address
@end

// Define an object with one embedded object
@interface Contact : RLMObject
@property NSString *name;

// Embed a single object.
@property Address *address;
@end

@implementation Contact
@end

// Define an object with an array of embedded objects
@interface Business : RLMObject
@property NSString *name;
// Embed an array of objects
@property RLMArray<Address *><Address> *addresses;
@end

```

#### Swift

You can define an embedded object by deriving from the
`EmbeddedObject`
class. You can use your embedded object in another model as you
would any other type.

```swift
class Person: Object {
    @Persisted(primaryKey: true) var id = 0
    @Persisted var name = ""

    // To-many relationship - a person can have many dogs
    @Persisted var dogs: List<Dog>

    // Inverse relationship - a person can be a member of many clubs
    @Persisted(originProperty: "members") var clubs: LinkingObjects<DogClub>

    // Embed a single object.
    // Embedded object properties must be marked optional.
    @Persisted var address: Address?

    convenience init(name: String, address: Address) {
        self.init()
        self.name = name
        self.address = address
    }
}

class DogClub: Object {
    @Persisted var name = ""
    @Persisted var members: List<Person>

    // DogClub has an array of regional office addresses.
    // These are embedded objects.
    @Persisted var regionalOfficeAddresses: List<Address>

    convenience init(name: String, addresses: [Address]) {
        self.init()
        self.name = name
        self.regionalOfficeAddresses.append(objectsIn: addresses)
    }
}

class Address: EmbeddedObject {
    @Persisted var street: String?
    @Persisted var city: String?
    @Persisted var country: String?
    @Persisted var postalCode: String?
}

```

---

### Guides Model Data Supported Types (`docs/guides/model-data/supported-types.md`)

# Supported Types - Swift SDK
## Collection Types
Realm has several types to represent groups of objects,
which we call **collections**. A collection is an object that contains
zero or more instances of one Realm type. Realm collections are **homogenous**:
all objects in a collection are of the same type.

You can filter and sort any collection using Realm's
query engine. Collections are
live, so they always reflect the current state
of the realm instance on the current thread. You can also
listen for changes in the collection by subscribing to collection
notifications.

All collection types conform to the `RealmCollection` protocol. This protocol inherits from
`CollectionType`, so you can use
a Realm collection as you would any other standard library
collections.

Using the RealmCollection protocol, you can write generic code that can
operate on any Realm collection:

```swift
func operateOn<C: RealmCollection>(collection: C) {
    // Collection could be either Results or List
    print("operating on collection containing \(collection.count) objects")
}

```

### Results and Sectioned Results
The Swift SDK `Results` collection is
a class representing objects retrieved from queries. A
`[Results` collection represents the
lazily-evaluated results of a query operation. Results are immutable:
you cannot add or remove elements to or from the results collection.
Results have an associated query that determines their contents.

The Swift SDK also provides `SectionedResults`,
a type-safe collection which holds `ResultsSection` as its elements.
Each `ResultSection` is a results
collection that contains only objects that belong to a given section key.

For example, an app that includes a contact list might use SectionedResults
to display a list of contacts divided into sections, where each section
contains all the contacts whose first name starts with the given letter.
The `ResultsSection` whose key is "L" would contain "Larry", "Liam",
and "Lisa".

> Seealso:
> Reads
>

### Collections as Properties
The Swift SDK also offers several collection types you can use as properties
in your data model:

1. `List`, a class representing
to-many relationships in models.
2. `LinkingObjects`, a class
representing inverse relationships in models.
3. MutableSet, a class representing
a to-many relationship.
4. Map, a class representing an associative array of key-value
pairs with unique keys.
5. `AnyRealmCollection`, a [type-erased](https://en.wikipedia.org/wiki/Type_erasure) class that can forward calls to a concrete Realm collection like Results, List or LinkingObjects.

### Collections are Live
Like live objects, Realm collections
are usually **live**:

- Live results collections always reflect the current results of the associated query.
- Live lists always reflect the current state of the relationship on the realm instance.

There are two cases when a collection is **not** live:

- The collection is unmanaged. For example, a List property of
a Realm object that has not been added to a realm yet
or that has been copied from a realm is not live.
- The collection is frozen.

Combined with collection notifications, live collections enable
clean, reactive code. For example, suppose your view displays the
results of a query. You can keep a reference to the results collection
in your view class, then read the results collection as needed without
having to refresh it or validate that it is up-to-date.

> Important:
> Since results update themselves automatically, do not
store the positional index of an object in the collection
or the count of objects in a collection. The stored index
or count value could be outdated by the time you use
it.
>

## Supported Property Types
You can use the following types to define your object model
properties.

### Property Cheat Sheet
#### Swift

> Version changed: 10.10.0
> `@Persisted` property declaration syntax
>

|Type|Required|Optional|
| --- | --- | --- |
|Bool|`@Persisted var boolName: Bool`|`@Persisted var optBoolName: Bool?`|
|Int, Int8, Int16, Int32, Int64|`@Persisted var intName: Int`|`@Persisted var optIntName: Int?`|
|Float|`@Persisted var floatName: Float`|`@Persisted var optFloatName: Float?`|
|Double|`@Persisted var doubleName: Double`|`@Persisted var optDoubleName: Double?`|
|String|`@Persisted var stringName: String`|`@Persisted var optStringName: String?`|
|Data|`@Persisted var dataName: Data`|`@Persisted var optDataName: Data?`|
|Date|`@Persisted var dateName: Date`|`@Persisted var optDateName: Date?`|
|Decimal128|`@Persisted var decimalName: Decimal128`|`@Persisted var optDecimalName: Decimal128?`|
|`UUID`|`@Persisted var uuidName: UUID`|`@Persisted var optUuidName: UUID?`|
|`ObjectId`|`@Persisted var objectIdName: ObjectId`|`@Persisted var optObjectIdName: ObjectId?`|
|`List`|`@Persisted var listName: List<MyCustomObjectType>`|N/A|
|MutableSet|`@Persisted var mutableSetName: MutableSet<String>`|N/A|
|Map|`@Persisted var mapName: Map<String, String>`|N/A|
|AnyRealmValue|`@Persisted var anyRealmValueName: AnyRealmValue`|N/A|
|User-defined `Object`|N/A|`@Persisted var optObjectPropertyName: MyCustomObjectType?`|
|User-defined `EmbeddedObject`|N/A|`@Persisted var optEmbeddedObjectPropertyName: MyEmbeddedObjectType?`|
|User-defined `Enums`|`@Persisted var enumName: MyPersistableEnum`|`@Persisted var optEnumName: MyPersistableEnum?`|

`CGFloat` properties are discouraged, as the type is not
platform independent.

To use Key-Value Coding with a user-defined object in the `@Persisted`
syntax, add the `@objc` attribute: `@Persisted @objc var myObject: MyClass?`

##### Setting Default Values
With the `@Persisted` property declaration syntax, you may see a
performance impact when setting default values for:

- `List`
- `MutableSet`
- `Dictionary`
- `Decimal128`
- `UUID`
- `ObjectId`

`@Persisted var listProperty: List<Int>` and `@Persisted var
listProperty = List<Int>()` are both valid, and are functionally
equivalent. However, the second declaration will result in poorer
performance.

This is because the List is created when the parent object is
created, rather than lazily as needed. For most types, this is
a difference so small you can't measure it. For the types listed
here, you may see a performance impact when using the second
declaration style.

#### Objective-C

|Type|Required|Optional|
| --- | --- | --- |
|Boolean|`@property BOOL boolName;`|`@property NSNumber<RLMBool> *optBoolName;`|
|Integer|`@property int intName;`|`@property NSNumber<RLMInt> *optIntName;`|
|Float|`@property float floatName;`|`@property NSNumber<RLMFloat> *optFloatName;`|
|Double|`@property double doubleName;`|`@property NSNumber<RLMDouble> *optDoubleName;`|
|String|`@property NSString *stringName;`|`@property NSString *optStringName;`|
|Data|`@property NSData *dataName;`|`@property NSData *optDataName;`|
|Date|`@property NSDate *dateName;`|`@property NSDate *optDateName;`|
|Decimal128|`@property RLMDecimal128 *decimalName;`|`@property RLMDecimal128 *optDecimalName;`|
|NSUUID|`@property NSUUID *uuidName;`|`@property NSUUID *optUuidName;`|
|`RLMObjectId`|`@property RLMObjectId *objectIdName;`|`@property RLMObjectId *optObjectIdName;`|
|`RLMArray`|`@property RLMArray<MyObject *><MyObject> *arrayName;`|N/A|
|`RLMSet`|`@property RLMSet<RLMString> *setName;`|N/A|
|`RLMDictionary`|`@property RLMDictionary<NSString *, NSString *><RLMString, RLMString> *dictionaryName;`|N/A|
|User-defined `RLMObject`|N/A|`@property MyObject *optObjectPropertyName;`|
|User-defined `RLMEmbeddedObject`|N/A|`@property MyEmbeddedObject *optEmbeddedObjectPropertyName;`|

Additionally:

- Integral types `int`, `NSInteger`, `long`, `long long`

`CGFloat` properties are discouraged, as the type is not
platform independent.

#### Swift Pre 10.10.0

> Version changed: 10.8.0
> `RealmProperty` replaces `RealmOptional`
>

|Type|Required|Optional|
| --- | --- | --- |
|Bool|`@objc dynamic var value = false`|`let value = RealmProperty<Bool?>()`|
|Int, Int8, Int16, Int32, Int64|`@objc dynamic var value = 0`|`let value = RealmProperty<Int?>()`|
|Float|`@objc dynamic var value: Float = 0.0`|`let value = RealmProperty<Float?>()`|
|Double|`@objc dynamic var value: Double = 0.0`|`let value = RealmProperty<Double?>()`|
|String|`@objc dynamic var value = ""`|`@objc dynamic var value: String? = nil`|
|Data|`@objc dynamic var value = Data()`|`@objc dynamic var value: Data? = nil`|
|Date|`@objc dynamic var value = Date()`|`@objc dynamic var value: Date? = nil`|
|Decimal128|`@objc dynamic var decimal: Decimal128 = 0`|`@objc dynamic var decimal: Decimal128?`|
|`UUID`|`@objc dynamic var uuid = UUID()`|`@objc dynamic var uuidOpt: UUID?`|
|`ObjectId`|`@objc dynamic var objectId = ObjectId.generate()`|`@objc dynamic var objectId: ObjectId?`|
|`List`|`let value = List<Type>()`||
|MutableSet|`let value = MutableSet<Type>()`||
|Map|`let value = Map<String, String>()`||
|AnyRealmValue|`let value = RealmProperty<AnyRealmValue>()`|N/A|
|User-defined `Object`|N/A|`@objc dynamic var value: MyClass?`|

Additionally:

- `EmbeddedObject`-derived types
- `Enum`

You can use `RealmProperty <T?>` to
represent integers, doubles, and other types as optional.

`CGFloat` properties are discouraged, as the type is not
platform independent.

### Unique Identifiers
> Version added: 10.8.0
> `UUID` type
>

`ObjectId` is a 12-byte unique value. `UUID` is a
16-byte globally-unique value. You can index
both types, and use either as a primary key.

> Note:
> When declaring default values for `@Persisted` UUID or ObjectId property
attributes, both of these syntax types are valid:
>
> - `@Persisted var value: UUID`
> - `@Persisted var value = UUID()`
>
> However, the second will result in poorer performance. This is because the
latter creates a new identifier that is never used any time an object is
read from the realm, while the former only creates them when needed.
>
> `@Persisted var id: ObjectId` has equivalent behavior to `@objc dynamic
var _id = ObjectId.generate()`. They both make random ObjectIds.
>
> `@Persisted var _id = ObjectId()` has equivalent behavior to `@objc
dynamic var _id = ObjectId()`. They both make zero-initialized ObjectIds.
>

### Size Limitations
Data and string properties cannot hold more than 16MB. To store
larger amounts of data, either:

- Break the data into 16MB chunks, or
- Store data directly on the file system and store paths to the files in the realm.

Realm throws a runtime exception if your app attempts to
store more than 16MB in a single property.

To avoid size limitations and a performance impact, it is best not to
store large blobs, such as image and video files, directly in a
realm. Instead, save the file to a file store and keep only the
location of the file and any relevant metadata in the realm.

### AnyRealmCollection
To store a collection as a property or variable without needing to know
the concrete collection type, Swift's type system requires a type-erased
wrapper like `AnyRealmCollection`:

```swift
class ViewController {
//    let collection: RealmCollection
//                    ^
//                    error: protocol 'RealmCollection' can only be used
//                    as a generic constraint because it has Self or
//                    associated type requirements
//
//    init<C: RealmCollection>(collection: C) where C.ElementType == MyModel {
//        self.collection = collection
//    }

    let collection: AnyRealmCollection<MyModel>

    init<C: RealmCollection & _ObjcBridgeable>(collection: C) where C.ElementType == MyModel {
        self.collection = AnyRealmCollection(collection)
    }
}

```

### Mutable Set
> Version added: 10.8.0

A `MutableSet`
collection represents a to-many relationship
containing distinct values. A `MutableSet` supports the following types
(and their optional versions):

- Bool
- Data
- Date
- Decimal128
- Double
- Float
- Int
- Int8
- Int16
- Int32
- Int64
- Object
- ObjectId
- String
- UUID

Like Swift's [Set](https://developer.apple.com/documentation/swift/set), `MutableSet` is a
generic type that is parameterized on the type it stores. Unlike
[native Swift collections](https://developer.apple.com/documentation/swift/swift_standard_library/collections),
Realm mutable sets are reference types, as opposed to value
types (structs).

You can only call the `MutableSets` mutation methods during a write
transaction. As a result, `MutableSets` are immutable if you open the
managing realm as a read-only realm.

You can filter and sort a `MutableSet` with the same predicates as Results. Like other
Realm collections, you can register a change listener on a `MutableSet`.

For example, a `Dog` class model might contain a `MutableSet` for
`citiesVisited`:

```swift
class Dog: Object {
    @Persisted var name = ""
    @Persisted var currentCity = ""
    @Persisted var citiesVisited: MutableSet<String>
}
```

> Note:
> When declaring default values for `@Persisted` MutableSet property attributes,
both of these syntax types is valid:
>
> - `@Persisted var value: MutableSet<String>`
> - `@Persisted var value = MutableSet<String>()`
>
> However, the second will result in significantly worse performance. This is
because the MutableSet is created when the parent object is created, rather than
lazily as needed.
>

### Map/Dictionary
> Version added: 10.8.0

The `Map` is an associative array that
contains key-value pairs with unique keys.

Like Swift's [Dictionary](https://developer.apple.com/documentation/swift/dictionary),
`Map` is a generic type that is parameterized on its key and value
types. Unlike [native Swift collections](https://developer.apple.com/documentation/swift/swift_standard_library/collections),
Realm Maps are reference types (classes), as opposed to
value types (structs).

You can declare a Map as a property of an object:

```swift
class Dog: Object {
    @Persisted var name = ""
    @Persisted var currentCity = ""

    // Map of city name -> favorite park in that city
    @Persisted var favoriteParksByCity: Map<String, String>
}
```

Realm disallows the use of `.` or `$` characters in map keys.
You can use percent encoding and decoding to store a map key that contains
one of these disallowed characters.

```
// Percent encode . or $ characters to use them in map keys
let mapKey = "New York.Brooklyn"
let encodedMapKey = "New York%2EBrooklyn"

```

> Note:
> When declaring default values for `@Persisted` Map property attributes, both
of these syntax types is valid:
>
> - `@Persisted var value: Map<String, String>`
> - `@Persisted var value = Map<String, String>()`
>
> However, the second will result in significantly worse performance. This is
because the Map is created when the parent object is created, rather than
lazily as needed.
>

### AnyRealmValue
> Version changed: 10.51.0
> `AnyRealmValue` properties can hold lists or maps of mixed data.
>

> Version added: 10.8.0

`AnyRealmValue` is a Realm property type that can hold different
data types. Supported `AnyRealmValue` data types include:

- Int
- Float
- Double
- Decimal128
- ObjectID
- UUID
- Bool
- Date
- Data
- String
- List
- Map
- Object

`AnyRealmValue` *cannot* hold a `MutableSet` or embedded object.

This mixed data type
is indexable, but you can't use it as a
primary key. Because `null` is a
permitted value, you can't declare an `AnyRealmValue` as optional.

```swift
class Dog: Object {
    @Persisted var name = ""
    @Persisted var currentCity = ""

    @Persisted var companion: AnyRealmValue
}
```

#### Collections as Mixed
In version 10.51.0 and later, a `AnyRealmValue` data type can
contain collections (a list or map, but *not* a set) of `AnyRealmValue`
elements. You can use mixed collections to
model unstructured or variable data. For more information, refer to
Define Unstructured Data.

- You can nest mixed collections up to 100 levels.
- You can query mixed collection properties and
register a listener for changes,
as you would a normal collection.
- You can find and update individual mixed collection elements
- You *cannot* store sets or embedded objects in mixed collections.

To use mixed collections in your app, define the `AnyRealmValue` type
property in your data model.
Then, you can create the list or map collections like any other mixed data value.

### Geospatial Data
> Version added: 10.47.0

Geospatial data, or "geodata", specifies points and geometric objects on
the Earth's surface.

If you want to persist geospatial data, it must conform to the
[GeoJSON spec](https://datatracker.ietf.org/doc/html/rfc7946).

To persist geospatial data with the Swift SDK, create a GeoJSON-compatible
embedded class that you can use in your data model.

Your custom embedded object must contain the two fields required by the
GeoJSON spec:

- A field of type `String` property that maps to a `type` property with
the value of `"Point"`: `@Persisted var type: String = "Point"`
- A field of type `List<Double>` that maps to a `coordinates`
property containing a latitude/longitude pair:
`@Persisted private var coordinates: List<Double>`

```swift
class CustomGeoPoint: EmbeddedObject {
    @Persisted private var type: String = "Point"
    @Persisted private var coordinates: List<Double>

    public var latitude: Double { return coordinates[1] }
    public var longitude: Double { return coordinates[0] }

    convenience init(_ latitude: Double, _ longitude: Double) {
        self.init()
        // Longitude comes first in the coordinates array of a GeoJson document
        coordinates.append(objectsIn: [longitude, latitude])
    }
}

```

## Map Unsupported Types to Supported Types
> Version added: 10.20.0

You can use Type Projection to persist unsupported types as supported types
in Realm. This enables you to work with Swift types that Realm
does not support, but store them as types that Realm does support. You could
store a URL as a `String`, for example, but read it from
Realm and use it in your application as though it were a URL.

### Declare Type Projections
To use type projection with Realm:

1. Use one of Realm's custom type protocols to map an unsupported data type
to a type that Realm supports
2. Use the projected types as @Persisted properties in the Realm object
model

#### Conform to the Type Projection Protocol
You can map an unsupported data type to a type that Realm supports using one of the Realm type projection protocols.

The Swift SDK provides two type projection protocols:

- CustomPersistable
- FailableCustomPersistable

Use `CustomPersistable`
when there is no chance the conversion can fail.

Use `FailableCustomPersistable`
when it is possible for the conversion to fail.

```
/* Detailed source-code truncated for AI context efficiency. */
```

> Seealso:
> These are protocols modeled after Swift's built-in [RawRepresentable](https://developer.apple.com/documentation/swift/rawrepresentable).
>

##### Supported PersistedTypes
The `PersistedType` can use any of the primitive types that the
Swift SDK supports. It can also be
an Embedded Object.

`PersistedType` cannot be an optional or a collection. However you can use the mapped type as an
optional or collection property in your object model.

```swift
extension URL: FailableCustomPersistable {
   // The `PersistedType` cannot be an optional, so this is not a valid
   // conformance to the FailableCustomPersistable protocol.
   public typealias PersistedType = String?
   ...
}

class Club: Object {
   @Persisted var id: ObjectId
   @Persisted var name: String
   // Although the `PersistedType` cannot be optional, you can use the
   // custom-mapped type as an optional in your object model.
   @Persisted var url: URL?
}
```

#### Use Type Projection in the Model
A type that conforms to one of the type projection protocols can be used with
the `@Persisted` property declaration syntax introduced in Swift SDK
version 10.10.0. It does not work with the `@objc dynamic` syntax.

You can use projected types for:

- Top-level types
- Optional versions of the type
- The types for a collection

When using a `FailableCustomPersistable` as a property, define it as an
optional property. When it is optional, the `FailableCustomPersistable`
protocol maps invalid values to `nil`. When it is a required property, it is
force-unwrapped. If you have a value that can't be converted to the projected
type, reading that property throws an unwrapped fail exception.

```swift
class Club: Object {
    @Persisted var id: ObjectId
    @Persisted var name: String
    // Since we declared the URL as a FailableCustomPersistable,
    // it must be optional.
    @Persisted var url: URL?
    // Here, the `location` property maps to an embedded object.
    // We can declare the property as required.
    // If the underlying field contains nil, this becomes
    // a default-constructed instance of CLLocationCoordinate
    // with field values of `0`.
    @Persisted var location: CLLocationCoordinate2D
}

public class Location: EmbeddedObject {
    @Persisted var latitude: Double
    @Persisted var longitude: Double
}

```

When your model contains projected types, you can create the object with values using the persisted type, or
by assigning to the field properties of an initialized object using the
projected types.

```swift
// Initialize objects and assign values
let club = Club(value: ["name": "American Kennel Club", "url": "https://akc.org"])
let club2 = Club()
club2.name = "Continental Kennel Club"
// When assigning the value to a type-projected property, type safety
// checks for the mapped type - not the persisted type.
club2.url = URL(string: "https://ckcusa.com/")!
club2.location = CLLocationCoordinate2D(latitude: 40.7509, longitude: 73.9777)

```

##### Type Projection in the Schema
When you declare your type as conforming to a type projection protocol, you
specify the type that should be persisted in realm. For example, if
you map a custom type `URL` to a persisted type of `String`, a `URL`
property appears as a `String` in the schema, and dynamic access to the
property acts on strings.

The schema does not directly represent mapped types. Changing a property
from its persisted type to its mapped type, or vice versa, does not require
a migration.

---

### Guides Realm Files Bundle A Realm (`docs/guides/realm-files/bundle-a-realm.md`)

# Bundle a Realm File - Swift SDK

Realm supports **bundling** realm files. When you bundle
a realm file, you include a database and all of its data in your
application download.

This allows users to start applications for the first time with a set of
initial data.

## Overview
To create and bundle a realm file with your application:

1. Create a realm file that
contains the data you'd like to bundle.
2. Bundle the realm file in your
production application.
3. In your production application,
open the realm from the bundled asset file.

## Create a Realm File for Bundling
1. Build a temporary realm app that shares the data model of your
application.
2. Open a realm and add the data you wish to bundle.
3. Use the `writeCopy(configuration:)`
method to copy the realm to a new file:

> Tip:
> If your app accesses Realm in an `async/await` context, mark the code
with `@MainActor` to avoid threading-related crashes.
>

`writeCopy(configuration: )`
automatically compacts your realm to the smallest possible size before
copying.

## Bundle a Realm File in Your Production Application
Now that you have a copy of the realm that contains the initial data,
bundle it with your production application. At a broad level, this entails:

1. Create a new project with the exact same data models as your production
app. Open a realm and add the data you wish to bundle. Since realm
files are cross-platform, you can do this in a macOS app.
2. Drag the compacted copy of your realm file to your production app's Xcode
Project Navigator.
3. Go to your app target's Build Phases tab in Xcode. Add the
realm file to the Copy Bundle Resources build phase.
4. At this point, your app can access the bundled realm file. Find its path
with [Bundle.main.path(forResource:ofType)](https://developer.apple.com/documentation/foundation/bundle/1410989-path).

You can open the realm at the bundle path directly if the
`readOnly` property is set to `true` on the
`Realm.Configuration`. If
you want to modify the bundled realm, first copy the bundled file to
your app's Documents folder with setting `seedFilePath` with the URL of the bundled Realm on your Configuration.

> Tip:
> See the [migration sample app](https://github.com/realm/realm-swift/tree/master/examples/ios/swift/Migration) for a
complete working app that uses a bundled local realm.
>

## Open a Realm from a Bundled Realm File
Now that you have a copy of the realm included with your production
application, you need to add code to use it. Use the `seedFilePath`
method when configuring your realm to open the realm
from the bundled file:

> Tip:
> If your app accesses Realm in an `async/await` context, mark the code
with `@MainActor` to avoid threading-related crashes.
>

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Guides Realm Files Compacting (`docs/guides/realm-files/compacting.md`)

# Reduce Realm File Size - Swift SDK
## Overview
The size of a realm file is always larger than the total
size of the objects stored within it. This architecture enables some of
realm's great performance, concurrency, and safety benefits.

Realm writes new data within unused space tracked inside a
file. In some situations, unused space may comprise a significant
portion of a realm file. Realm's default behavior is to automatically
compact a realm file to prevent it from growing too large.
You can use manual compaction strategies when
automatic compaction is not sufficient for your use case
or you're using a version of the SDK that doesn't have automatic
compaction.

## Realm File Size
Generally, a realm file takes less space on disk than a
comparable SQLite database. These factors can affect
file size:

- Pinning transactions
- Threading
- Dispatch Queues

When you consider reducing the file size through compacting, there are a
couple of things to keep in mind:

- Compacting can be a resource-intensive operation
- Compacting can block the UI thread

Because of these factors, you probably don't want to compact a realm every
time you open it, but instead want to consider when to compact a
realm. This varies based on your application's
platform and usage patterns. When deciding when to compact, consider iOS
file size limitations.

### Avoid Pinning Transactions
Realm ties read transaction lifetimes to the memory lifetime
of realm instances. Avoid "pinning" old Realm transactions.
Use auto-refreshing realms, and wrap the use of Realm APIs
from background threads in explicit autorelease pools.

### Threading
Realm updates the version of your data that it accesses at
the start of a run loop iteration. While this gives you a consistent
view of your data, it has file size implications.

Imagine this scenario:

- **Thread A**: Read some data from a realm, and then block the thread on a
long-running operation.
- **Thread B**: Write data on another thread.
- **Thread A**: The version on the read thread isn't updated. Realm has
to hold intermediate versions of the data, growing in file size with
every write.

To avoid this issue, call `invalidate()`
on the realm. This tells the realm that you no longer need the
objects you've read so far. This frees realm from tracking
intermediate versions of those objects. The next time you access it,
realm will have the latest version of the objects.

You can also use these two methods to compact your Realm:

- Set `shouldCompactOnLaunch`
in the configuration
- Use `writeCopy(toFile:encryptionKey:)`

> Seealso:
> Advanced Guides: Threading
>

### Dispatch Queues
When accessing Realm using [Grand Central Dispatch](https://developer.apple.com/documentation/dispatch), you may see similar file growth. A dispatch
queue's autorelease pool may not drain immediately upon executing your
code. Realm cannot reuse intermediate versions of the data until the
dispatch pool deallocates the realm object. Use an explicit
autorelease pool when accessing realm from a dispatch queue.

## Automatic Compaction
> Version added: 10.35.0

The SDK automatically compacts Realm files in the background by continuously reallocating data
within the file and removing unused file space. Automatic compaction is sufficient for minimizing the Realm file size
for most applications.

Automatic compaction begins when the size of unused space in the file is more than twice the size of user
data in the file. Automatic compaction only takes place when
the file is not being accessed.

## Manual Compaction
Manual compaction can be used for applications that
require stricter management of file size or that use an older version
of the SDK that does not support automatic compaction.

Realm manual compaction works by:

1. Reading the entire contents of the realm file
2. Writing the contents to a new file at a different location
3. Replacing the original file

If the file contains a lot of data, this can be an expensive operation.

Use `shouldCompactOnLaunch()`
(Swift) or `shouldCompactOnLaunch`
(Objective-C) on a realm's configuration object to compact a realm.
Specify conditions to execute this method, such as:

- The size of the file on disk
- How much free space the file contains

For more information about the conditions to execute in the method, see:
Tips for Using Manual Compaction.

> Important:
> Compacting cannot occur while a realm is being accessed,
regardless of any configuration settings.
>

#### Objective-C

```objectivec
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.shouldCompactOnLaunch = ^BOOL(NSUInteger totalBytes, NSUInteger usedBytes) {
    // totalBytes refers to the size of the file on disk in bytes (data + free space)
    // usedBytes refers to the number of bytes used by data in the file

    // Compact if the file is over 100MB in size and less than 50% 'used'
    NSUInteger oneHundredMB = 100 * 1024 * 1024;
    return (totalBytes > oneHundredMB) && ((double)usedBytes / totalBytes) < 0.5;
};

NSError *error = nil;
// Realm is compacted on the first open if the configuration block conditions were met.
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];
if (error) {
    // handle error compacting or opening Realm
}

```

#### Swift

```swift
let config = Realm.Configuration(shouldCompactOnLaunch: { totalBytes, usedBytes in
    // totalBytes refers to the size of the file on disk in bytes (data + free space)
    // usedBytes refers to the number of bytes used by data in the file

    // Compact if the file is over 100MB in size and less than 50% 'used'
    let oneHundredMB = 100 * 1024 * 1024
    return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
})
do {
    // Realm is compacted on the first open if the configuration block conditions were met.
    let realm = try Realm(configuration: config)
} catch {
    // handle error compacting or opening Realm
}

```

### Compact a Realm Asynchronously
When you use the Swift async/await syntax to open a realm asynchronously,
you can compact a realm in the background.

```swift
func testAsyncCompact() async {
    let config = Realm.Configuration(shouldCompactOnLaunch: { totalBytes, usedBytes in
        // totalBytes refers to the size of the file on disk in bytes (data + free space)
        // usedBytes refers to the number of bytes used by data in the file

        // Compact if the file is over 100MB in size and less than 50% 'used'
        let oneHundredMB = 100 * 1024 * 1024
        return (totalBytes > oneHundredMB) && (Double(usedBytes) / Double(totalBytes)) < 0.5
    })

    do {
        // Realm is compacted asynchronously on the first open if the
        // configuration block conditions were met.
        let realm = try await Realm(configuration: config)
    } catch {
        // handle error compacting or opening Realm
    }
}

```

Starting with Realm Swift SDK Versions 10.15.0 and 10.16.0, many of the
Realm APIs support the Swift async/await syntax. Projects must
meet these requirements:

|Swift SDK Version|Swift Version Requirement|Supported OS|
| --- | --- | --- |
|10.25.0|Swift 5.6|iOS 13.x|
|10.15.0 or 10.16.0|Swift 5.5|iOS 15.x|

If your app accesses Realm in an `async/await` context, mark the code
with `@MainActor` to avoid threading-related crashes.

### Make a Compacted Copy
You can save a compacted (and optionally encrypted) copy of a realm to another file location
with the `Realm.writeCopy(toFile:encryptionKey:)`
method. The destination file cannot already exist.

> Important:
> Avoid calling this method within a write transaction. If called within a write transaction, this
method copies the absolute latest data. This includes any
**uncommitted** changes you made in the transaction before this
method call.
>

### Tips for Using Manual Compaction
Compacting a realm can be an expensive operation that can block
the UI thread. Your application should not compact every time you open
a realm. Instead, try to optimize compacting so your application does
it just often enough to prevent the file size from growing too large.
If your application runs in a resource-constrained environment,
you may want to compact when you reach a certain file size or when the
file size negatively impacts performance.

These recommendations can help you optimize manual compaction for your
application:

- Set the max file size to a multiple of your average realm state
size. If your average realm state size is 10MB, you might set the max
file size to 20MB or 40MB, depending on expected usage and device
constraints.
- As a starting point, compact realms when more than 50% of the realm file
size is no longer in use. Divide the currently used bytes by the total
file size to determine the percentage of space that is currently used.
Then, check for that to be less than 50%. This means that greater than
50% of your realm file size is unused space, and it is a good time to
compact. After experimentation, you may find a different percentage
works best for your application.

These calculations might look like this in your `shouldCompactOnLaunch`
callback:

```swift
// Set a maxFileSize equal to 20MB in bytes
let maxFileSize = 20 * 1024 * 1024
// Check for the realm file size to be greater than the max file size,
// and the amount of bytes currently used to be less than 50% of the
// total realm file size
return (realmFileSizeInBytes > maxFileSize) && (Double(usedBytes) / Double(realmFileSizeInBytes)) < 0.5
```

Experiment with conditions to find the right balance of how often to
compact realm files in your application.

#### Consider iOS File Size Limitations
A large realm file can impact the performance and reliability of
your app. Any single realm file cannot be larger than the amount
of memory your application would be allowed to map in iOS. This limit
depends on the device and on how fragmented the memory space is at
that point in time.

If you need to store more data, map it over multiple realm files.

## Summary
- Realm's architecture enables threading-related benefits,
but can result in file size growth.
- Automatic compaction manages file size growth when the file is not being accessed.
- Manual compaction strategies like `shouldCompactOnLaunch()` can be used when automatic compaction does not meet application needs.
- Compacting cannot occur if another process is accessing the realm.
- You can compact a realm in the background when you use async/await syntax.

---

### Guides Realm Files Configure And Open A Realm (`docs/guides/realm-files/configure-and-open-a-realm.md`)

# Configure & Open a Realm - Swift SDK
When you open a realm, you can pass a `Realm.Configuration` that specifies additional details
about how to configure the realm file. This includes things like:

- Pass a fileURL or in-memory identifier to customize how the realm is stored on device
- Specify the realm use only a subset of your app's classes
- Whether and when to compact a realm to reduce its file size
- Pass an encryption key to encrypt a realm
- Provide a schema version or migration block when making schema changes

## Open a Realm
You can open a local realm with several different configuration
options:

- No configuration - i.e. default configuration
- Specify a file URL for the realm
- Open the realm only in memory, without saving a file to the file system

### Open a Default Realm or Realm at a File URL
#### Objective-C

You can open the default realm with [+[RLMRealm
defaultRealm]].

You can also pass a `RLMRealmConfiguration` object to
`+[RLMRealm realmWithConfiguration:error:]`
to open a realm at a specific file URL or in memory.

You can set the default realm configuration by passing a
RLMRealmConfiguration instance to
`+[RLMRealmConfiguration setDefaultConfiguration:]`.

```objectivec
// Open the default realm
RLMRealm *defaultRealm = [RLMRealm defaultRealm];

// Open the realm with a specific file URL, for example a username
NSString *username = @"GordonCole";
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration];
configuration.fileURL = [[[configuration.fileURL URLByDeletingLastPathComponent]
                         URLByAppendingPathComponent:username]
                         URLByAppendingPathExtension:@"realm"];
NSError *error = nil;
RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration
                                             error:&error];

```

#### Swift

You can open a realm with the `Realm()` initializer.
If you omit the `Realm.Configuration` parameter, you will open the
default realm.

You can set the default realm configuration by assigning a new
Realm.Configuration instance to the
`Realm.Configuration.defaultConfiguration`
class property.

```swift
// Open the default realm
let defaultRealm = try! Realm()

// Open the realm with a specific file URL, for example a username
let username = "GordonCole"
var config = Realm.Configuration.defaultConfiguration
config.fileURL!.deleteLastPathComponent()
config.fileURL!.appendPathComponent(username)
config.fileURL!.appendPathExtension("realm")
let realm = try! Realm(configuration: config)

```

### Open an In-Memory Realm

You can open a realm entirely in memory, which will not create a
`.realm` file or its associated auxiliary files. Instead the SDK stores objects in memory while the
realm is open and discards them immediately when all instances are
closed.

#### Objective-C

Set the `inMemoryIdentifier`
property of the realm configuration.

```objectivec
// Open the realm with a specific in-memory identifier.
NSString *identifier = @"MyRealm";
RLMRealmConfiguration *configuration = [[RLMRealmConfiguration alloc] init];
configuration.inMemoryIdentifier = identifier;
// Open the realm
RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration error:nil];

```

#### Swift

Set the `inMemoryIdentifier`
property of the realm configuration.

```swift
// Open the realm with a specific in-memory identifier.
let identifier = "MyRealm"
let config = Realm.Configuration(
    inMemoryIdentifier: identifier)
// Open the realm
let realm = try! Realm(configuration: config)

```

> Important:
> When all *in-memory* realm instances with a particular identifier
go out of scope, Realm deletes **all data** in that
realm. To avoid this, hold onto a strong reference to any
in-memory realms during your app's lifetime.
>

### Open a Realm with Swift Concurrency Features
You can use Swift's async/await syntax to open a MainActor-isolated realm,
or specify an actor when opening a realm asynchronously:

```swift
@MainActor
func mainThreadFunction() async throws {
    // These are identical: the async init produces a
    // MainActor-isolated Realm if no actor is supplied
    let realm1 = try await Realm()
    let realm2 = try await Realm(actor: MainActor.shared)

    try await useTheRealm(realm: realm1)
}

```

Or you can define a custom realm actor to manage all of your realm operations:

```
/* Detailed source-code truncated for AI context efficiency. */
```

An actor-isolated realm may be used with either local or global actors.

```swift
// A simple example of a custom global actor
@globalActor actor BackgroundActor: GlobalActor {
    static var shared = BackgroundActor()
}

@BackgroundActor
func backgroundThreadFunction() async throws {
    // Explicitly specifying the actor is required for anything that is not MainActor
    let realm = try await Realm(actor: BackgroundActor.shared)
    try await realm.asyncWrite {
        _ = realm.create(Todo.self, value: [
            "name": "Pledge fealty and service to Gondor",
            "owner": "Pippin",
            "status": "In Progress"
        ])
    }
    // Thread-confined Realms would sometimes throw an exception here, as we
    // may end up on a different thread after an `await`
    let todoCount = realm.objects(Todo.self).count
    print("The number of Realm objects is: \(todoCount)")
}

@MainActor
func mainThreadFunction() async throws {
    try await backgroundThreadFunction()
}

```

For more information about working with actor-isolated realms, refer to
Use Realm with Actors - Swift SDK.

## Close a Realm
There is no need to manually close a realm in Swift or Objective-C.
When a realm goes out of scope and is removed from memory due to
[ARC](https://docs.swift.org/swift-book/LanguageGuide/AutomaticReferenceCounting.html),
the realm is closed.

## Handle Errors When Accessing a Realm
#### Objective-C

To handle errors when accessing a realm, provide an
`NSError` pointer to the `error` parameter:

```objectivec
NSError *error = nil;
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];
if (!realm) {
    // Handle error
    return;
}
// Use realm

```

#### Swift

To handle errors when accessing a realm, use Swift's built-in
error handling mechanism:

```swift
do {
    let realm = try Realm()
    // Use realm
} catch let error as NSError {
    // Handle error
}

```

## Provide a Subset of Classes to a Realm
> Tip:
> Some applications, such as watchOS apps and iOS app extensions, have
tight constraints on their memory footprints. To optimize your data
model for low-memory environments, open the realm with a subset
of classes.
>

#### Objective-C

By default, the Swift SDK automatically adds all
`RLMObject`- and
`RLMEmbeddedObject`-derived
classes in your executable to the realm schema. You can control
which objects get added by setting the `objectClasses`
property of the `RLMRealmConfiguration` object.

```objectivec
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];

// Given a RLMObject subclass called `Task`
// Limit the realm to only the Task object. All other
// Object- and EmbeddedObject-derived classes are not added.
config.objectClasses = @[[Task class]];

NSError *error = nil;
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];

if (error != nil) {
    // Something went wrong
} else {
    // Use realm
}

```

#### Swift

By default, the Swift SDK automatically adds all
`Object`- and
`EmbeddedObject`-derived
classes in your executable to the realm schema. You can control
which objects get added by setting the `objectTypes`
property of the `Realm.Configuration` object.

```swift
var config = Realm.Configuration.defaultConfiguration

// Given: `class Dog: Object`
// Limit the realm to only the Dog object. All other
// Object- and EmbeddedObject-derived classes are not added.
config.objectTypes = [Dog.self]

let realm = try! Realm(configuration: config)

```

## Initialize Properties Using Realm APIs
You might define properties whose values are initialized using
Realm APIs. For example:

```swift
class SomeSwiftType {
    let persons = try! Realm().objects(Person.self)
    // ...
}
```

If this initialization code runs before you set up your Realm
configurations, you might get unexpected behavior. For example, if you
set a migration block for the default realm
configuration in `applicationDidFinishLaunching()`, but you create an
instance of `SomeSwiftType` before
`applicationDidFinishLaunching()`, you might be accessing your
realm before it has been correctly configured.

To avoid such issues, consider doing one of the following:

- Defer instantiation of any type that eagerly initializes properties using Realm APIs until after your app has completed setting up its realm configurations.
- Define your properties using Swift's `lazy` keyword. This allows you to safely instantiate such types at any time during your application's lifecycle, as long as you do not attempt to access your `lazy` properties until after your app has set up its realm configurations.
- Only initialize your properties using Realm APIs that explicitly take in user-defined configurations. You can be sure that the configuration values you are using have been set up properly before they are used to open realms.

## Use Realm When the Device Is Locked
By default, iOS 8 and above encrypts app files using
`NSFileProtection` whenever the device is locked. If your app attempts
to access a realm while the device is locked, you might see the
following error:

```text
open() failed: Operation not permitted
```

To handle this, downgrade the file protection of the folder containing
the Realm files.

> Tip:
> If you reduce iOS file encryption, consider using Realm's
built-in encryption to secure your data
instead.
>

This example shows how to apply a less strict protection level to the
parent directory of the default realm.

```swift
let realm = try! Realm()

// Get the realm file's parent directory
let folderPath = realm.configuration.fileURL!.deletingLastPathComponent().path

// Disable file protection for this directory after the user has unlocked the device once
try! FileManager.default.setAttributes([FileAttributeKey.protectionKey: FileProtectionType.completeUntilFirstUserAuthentication],
                                       ofItemAtPath: folderPath)

```

Realm may create and delete auxiliary files at any time.
Instead of downgrading file protection on the files, apply it to the
parent folder. This way, the file protection applies to all relevant
files regardless of creation time.

---

### Guides Realm Files Delete A Realm (`docs/guides/realm-files/delete-a-realm.md`)

# Delete a Realm File - Swift SDK
In some cases, you may want to completely delete a realm file from disk.

Realm avoids copying data into memory except when absolutely required.
As a result, all objects managed by a realm have references to the file
on disk. Before you can safely delete the file, you must ensure the
deallocation of these objects:

- All objects read from or added to the realm
- All List and Results objects
- All ThreadSafeReference objects
- The realm itself

> Warning:
> If you delete a realm file or any of its auxiliary files while one or
more instances of the realm are open, you might corrupt the realm or
disrupt sync.
>

## Delete a Realm File to Avoid Migration
If you iterate rapidly as you develop your app, you may want to delete a
realm file instead of migrating it when you make schema changes. The Realm
configuration provides a `deleteRealmIfMigrationNeeded`
parameter to help with this case.

When you set this property to `true`, the SDK deletes the realm file when
a migration would be required. Then, you can create objects that match the
new schema instead of writing migration blocks for development or test data.

```swift
do {
    // Delete the realm if a migration would be required, instead of migrating it.
    // While it's useful during development, do not leave this set to `true` in a production app!
    let configuration = Realm.Configuration(deleteRealmIfMigrationNeeded: true)
    let realm = try Realm(configuration: configuration)
} catch {
    print("Error opening realm: \(error.localizedDescription)")
}

```

## Delete a Realm File
In practice, there are two safe times to delete the realm file:

1. On application startup before ever opening the realm.
2. After only having opened the realm within an explicit `autorelease` pool, which ensures deallocation of all of objects within it.

---

### Guides Realm Files Encrypt A Realm (`docs/guides/realm-files/encrypt-a-realm.md`)

# Encrypt a Realm - Swift SDK
## Overview
You can encrypt the realm file on disk with AES-256 +
SHA-2 by supplying a 64-byte encryption key when opening a
realm.

Realm transparently encrypts and decrypts data with standard
[AES-256 encryption](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard) using the
first 256 bits of the given 512-bit encryption key. Realm
uses the other 256 bits of the 512-bit encryption key to validate
integrity using a [hash-based message authentication code
(HMAC)](https://en.wikipedia.org/wiki/HMAC).

> Warning:
> Do not use cryptographically-weak hashes for realm encryption keys.
For optimal security, we recommend generating random rather than derived
encryption keys.
>

> Note:
> You must encrypt a realm the first time you open it.
If you try to open an existing unencrypted realm using a configuration
that contains an encryption key, Realm throws an error.
>

## Considerations
The following are key impacts to consider when encrypting a realm.

### Storing & Reusing Keys
You **must** pass the same encryption key every time you open the encrypted realm.
If you don't provide a key or specify the wrong key for an encrypted
realm, the Realm SDK throws an error.

Apps should store the encryption key in the Keychain so that other apps
cannot read the key.

### Performance Impact
Reads and writes on encrypted realms can be up to 10% slower than unencrypted realms.

### Accessing an Encrypted Realm from Multiple Processes
> Version changed: 10.38.0

Starting with Realm Swift SDK version 10.38.0, Realm supports opening
the same encrypted realm in multiple processes.

If your app uses Realm Swift SDK version 10.37.2 or earlier, attempting to
open an encrypted realm from multiple processes throws this error:
`Encrypted interprocess sharing is currently unsupported.`

Apps using earlier SDK versions have two options to work with realms in
multiple processes:

- Use an unencrypted realm.
- Store data that you want to encrypt as `NSData` properties on realm
objects. Then, you can encrypt and decrypt individual fields.

One possible tool to encrypt and decrypt fields is [Apple's
CryptoKit framework](https://developer.apple.com/documentation/cryptokit). You can use [Swift
Crypto](https://github.com/apple/swift-crypto) to simplify app
development with CryptoKit.

## Example
The following code demonstrates how to generate an encryption key and
open an encrypted realm:

#### Objective-C

```objectivec
// Generate a random encryption key
NSMutableData *key = [NSMutableData dataWithLength:64];
(void)SecRandomCopyBytes(kSecRandomDefault, key.length, (uint8_t *)key.mutableBytes);

// Open the encrypted Realm file
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.encryptionKey = key;

NSError *error = nil;
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];
if (!realm) {
    // If the encryption key is wrong, `error` will say that it's an invalid database
    NSLog(@"Error opening realm: %@", error);
} else {
    // Use the realm as normal...
}

```

#### Swift

```swift
// Generate a random encryption key
var key = Data(count: 64)
_ = key.withUnsafeMutableBytes { (pointer: UnsafeMutableRawBufferPointer) in
    SecRandomCopyBytes(kSecRandomDefault, 64, pointer.baseAddress!) }

// Configure for an encrypted realm
var config = Realm.Configuration(encryptionKey: key)

do {
    // Open the encrypted realm
    let realm = try Realm(configuration: config)
    // ... use the realm as normal ...
} catch let error as NSError {
    // If the encryption key is wrong, `error` will say that it's an invalid database
    fatalError("Error opening realm: \(error.localizedDescription)")
}

```

The following Swift example demonstrates how to store and retrieve a
generated key from the Keychain:

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Guides Realm Files Realm Files (`docs/guides/realm-files/realm-files.md`)

# Work with Realm Files - Swift SDK
A **realm** is the core data structure used to organize data in
Realm. A realm is a collection of the objects that you use
in your application, called Realm objects, as well as additional metadata
that describe the objects. To learn how to define a Realm object, see
Define an Object Model.

## Realm Files
Realm stores a binary encoded version of every object and type in a
realm in a single `.realm` file. The file is located at a specific
path that you can define when you open the
realm. You can open, view, and edit the contents of these files with
Realm Studio.

### In-Memory Realms
You can also open a realm entirely in memory, which does not create a `.realm`
file or its associated auxiliary files. Instead the SDK stores objects in memory
while the realm is open and discards them immediately when all instances are
closed.

> See:
> To open an in-memory realm, refer to Open an In-Memory Realm.
>

### Default Realm
Calling `Realm()` or
`RLMRealm` opens the default realm.
This method returns a realm object that maps to a file named
`default.realm`. You can find this file:

- iOS: in the Documents folder of your app
- macOS: in the Application Support folder of your app

> See:
> To open a default realm, refer to Open a Default Realm or Realm at a File URL.
>

### Auxiliary Realm Files
Realm creates additional files for each realm:

- **realm files**, suffixed with "realm", e.g. default.realm:
contain object data.
- **lock files**, suffixed with "lock", e.g. default.realm.lock:
keep track of which versions of data in a realm are
actively in use. This prevents realm from reclaiming storage space
that is still used by a client application.
- **note files**, suffixed with "note", e.g. default.realm.note:
enable inter-thread and inter-process notifications.
- **management files**, suffixed with "management", e.g. default.realm.management:
internal state management.

Deleting these files has important implications.
For more information about deleting `.realm` or auxiliary files, see:
Delete a Realm

## Find a Realm File Path
The realm file is located at a specific path that you can optionally define
when you open the realm.

```swift
// Get on-disk location of the default Realm
let realm = try! Realm()
print("Realm is located at:", realm.configuration.fileURL!)
```

> See:
> To open a realm at a specific path, refer to Open a Default Realm or Realm at a File URL.
>

---

### Guides Realm Files Tvos (`docs/guides/realm-files/tvos.md`)

# Build for tvOS
## Overview
This page details considerations when using Realm on tvOS.

> Seealso:
> Install the SDK for iOS, macOS, tvOS, and watchOS
>

## Avoid Storing Important User Data
Avoid storing important user data in a realm on tvOS. Instead, it's
best to treat Realm as a rebuildable cache.

> Note:
> The reason for this has to do with where Realm writes its
Realm files. On other Apple platforms,
Realm writes its Realm files to the "Documents"
directory. Because tvOS restricts writes to that directory, the
default Realm file location on tvOS is instead `NSCachesDirectory`.
tvOS can purge files in that directory at any time, so reliable
long-term persistence is not possible.
>

You can also use Realm as an initial data source by
bundling prebuilt Realm files in your app.
Note that the [App Store guidelines](https://developer.apple.com/tvos/submit/) limit your
app size to 4GB.

> Tip:
> Browse our [tvOS examples](https://github.com/realm/realm-swift/tree/master/examples/tvos) for sample tvOS apps
that demonstrate how to use Realm as an offline cache.
>

## Share Realm Files with TV Services Extensions
To share a Realm file between a tvOS app and a
TV services extension such as [Top Shelf](https://developer.apple.com/design/human-interface-guidelines/tvos/overview/top-shelf/), use the
`Library/Caches/` directory in the shared container for the
application group:

```swift
let fileUrl = FileManager.default
    .containerURL(forSecurityApplicationGroupIdentifier: "group.com.mongodb.realm.examples.extension")!
    .appendingPathComponent("Library/Caches/default.realm")

```

---

### Guides Swiftui Configure And Open Realm (`docs/guides/swiftui/configure-and-open-realm.md`)

# Configure and Open a Realm - SwiftUI
The Swift SDK provides property wrappers to open a realm in a
SwiftUI-friendly way.

You can:

- Implicitly open a realm
with a `defaultConfiguration` or specify a different configuration.

## Open a Realm with a Configuration
When you use `@ObservedRealmObject`
or `@ObservedResults`, these
property wrappers implicitly open a realm and retrieve the specified
objects or results.

```swift
// Implicitly use the default realm's objects(Dog.self)
@ObservedResults(Dog.self) var dogs

```

> Note:
> The `@ObservedResults` property wrapper is intended for use in a
SwiftUI View. If you want to observe results in a view model, register
a change listener.
>

When you do not specify a configuration, these property wrappers use the
`defaultConfiguration`.
You can set the defaultConfiguration
globally, and property wrappers across the app can use that configuration
when they implicitly open a realm.

You can provide alternative configurations that the property wrappers use
to implicitly open the realm.
To do this, create explicit configurations.
Then, use environment injection to pass the respective configurations
to the views that need them.
Passing a configuration to a view where property wrappers open a realm
uses the passed configuration instead of the `defaultConfiguration`.

---

### Guides Swiftui Filter Data (`docs/guides/swiftui/filter-data.md`)

# Filter Data - SwiftUI
## Observe in SwiftUI Views
The `@ObservedResults` property wrapper used in the examples on this page
is intended for use in a SwiftUI View. If you want to observe results
in a view model instead, register a change listener.

## Search a Realm Collection
> Version added: 10.19.0

The Realm Swift SDK allows you to extend [.searchable](https://developer.apple.com/documentation/swiftui/view/searchable(text:placement:prompt:)-18a8f).
When you use `ObservedResults`
to query a realm, you can specify collection and keypath in the result set
to mark it as searchable.

The collection is the bound collection represented by your ObservedResults
query. In this example, it is the `dogs` variable that represents the
collection of all Dog objects in the realm.

The keypath is the object property that you want to search. In this
example, we search the dogs collection by dog name. The Realm Swift
`.searchable` implementation only supports keypaths with `String` types.

```swift
struct SearchableDogsView: View {
    @ObservedResults(Dog.self) var dogs
    @State private var searchFilter = ""
    
    var body: some View {
        NavigationView {
            // The list shows the dogs in the realm.
            List {
                ForEach(dogs) { dog in
                    DogRow(dog: dog)
                }
            }
            .searchable(text: $searchFilter,
                        collection: $dogs,
                        keyPath: \.name) {
                ForEach(dogs) { dogsFiltered in
                    Text(dogsFiltered.name).searchCompletion(dogsFiltered.name)
                }
            }
        }
    }
}

```

## Filter or Query a Realm with ObservedResults
The `@ObservedResults` property wrapper
opens a realm and returns all objects of the specified type. However, you
can filter or query `@ObservedResults` to use only a subset of the objects
in your view.

> Seealso:
> For more information about the query syntax and types of queries that Realm
supports, see: Read and Filter Data.
>

### Filter with an NSPredicate
To filter `@ObservedResults` using the NSPredicate Query API, pass an [NSPredicate](https://developer.apple.com/documentation/foundation/nspredicate) as an argument to `filter`:

```swift
struct FilterDogsViewNSPredicate: View {
    @ObservedResults(Dog.self, filter: NSPredicate(format: "weight > 40")) var dogs
    
    var body: some View {
        NavigationView {
            // The list shows the dogs in the realm.
            List {
                ForEach(dogs) { dog in
                    DogRow(dog: dog)
                }
            }
        }
    }
}

```

### Query with the Realm Type-Safe Query API
> Version added: 10.24.0
> Use *where* to perform type-safe queries on ObservedResults.
>

To use `@ObservedResults` with the Realm Type-Safe Query API, pass a query in a closure as an argument to
`where`:

```swift
struct FilterDogsViewTypeSafeQuery: View {
    @ObservedResults(Dog.self, where: ( { $0.weight > 40 } )) var dogs
    
    var body: some View {
        NavigationView {
            // The list shows the dogs in the realm.
            List {
                ForEach(dogs) { dog in
                    DogRow(dog: dog)
                }
            }
        }
    }
}

```

## Section Filtered Results
> Version added: 10.29.0

The `@ObservedSectionedResults`
property wrapper opens a realm and returns all objects of the specified type,
divided into sections by the specified key path. Similar to
`@ObservedResults` above, you can filter or query `@ObservedSectionedResults`
to use only a subset of the objects in your view:

```swift
@ObservedSectionedResults(Dog.self,
                          sectionKeyPath: \.firstLetter,
                          where: ( { $0.weight > 40 } )) var dogs

```

---

### Guides Swiftui Pass Realm Data Between Views (`docs/guides/swiftui/pass-realm-data-between-views.md`)

# Pass Realm Data Between SwiftUI Views
The Realm Swift SDK provides several ways to pass realm data between views:

- Pass Realm objects to a view
- Use environment injection to: Inject a partition value into a viewInject an opened realm into a viewInject a realm configuration into a view

## Pass Realm Objects to a View
When you use the `@ObservedRealmObject` or `@ObservedResults` property
wrapper, you implicitly open a realm and retrieve the specified objects
or results. You can then pass those objects to a view further down the
hierarchy.

```swift
struct DogsView: View {
    @ObservedResults(Dog.self) var dogs

    /// The button to be displayed on the top left.
    var leadingBarButton: AnyView?

    var body: some View {
        NavigationView {
            VStack {
                // The list shows the dogs in the realm.
                // The ``@ObservedResults`` above implicitly opens a realm and retrieves
                // all the Dog objects. We can then pass those objects to views further down the
                // hierarchy.
                List {
                    ForEach(dogs) { dog in
                        DogRow(dog: dog)
                    }.onDelete(perform: $dogs.remove)
                }.listStyle(GroupedListStyle())
                    .navigationBarTitle("Dogs", displayMode: .large)
                    .navigationBarBackButtonHidden(true)
                    .navigationBarItems(
                        leading: self.leadingBarButton,
                        // Edit button on the right to enable rearranging items
                        trailing: EditButton())
            }.padding()
        }
    }
}

```

## Pass Environment Values
[Environment](https://developer.apple.com/documentation/swiftui/environment) injection is a
useful tool in SwiftUI development with Realm.
Realm property wrappers provide different ways for you to
work with environment values when developing your SwiftUI application.

### Inject an Opened Realm
You can inject a realm that you opened in another SwiftUI view into
a view as an environment value. The property wrapper uses this passed-in
realm to populate the view:

```swift
ListView()
   .environment(\.realm, realm)
```

### Inject a Realm Configuration
You can use a realm other than the default realm by passing a different
configuration in an environment object.

```swift
LocalOnlyContentView()
.environment(\.realmConfiguration, Realm.Configuration( /* ... */ ))
```

---

### Guides Swiftui React To Changes (`docs/guides/swiftui/react-to-changes.md`)

# React to Changes - SwiftUI
## Observe an Object
The Swift SDK provides the `@ObservedRealmObject` property wrapper that invalidates a view
when an observed object changes. You can use this property wrapper to
create a view that automatically updates itself when the observed object
changes.

```swift
struct DogDetailView: View {
    @ObservedRealmObject var dog: Dog

    var body: some View {
        VStack {
            Text(dog.name)
                .font(.title2)
            Text("\(dog.name) is a \(dog.breed)")
            AsyncImage(url: dog.profileImageUrl) { image in
                            image.resizable()
                        } placeholder: {
                            ProgressView()
                        }
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 150, height: 150)
            Text("Favorite toy: \(dog.favoriteToy)")
        }
    }
}

```

## Observe Query Results
The Swift SDK provides the `@ObservedResults`
property wrapper that lets you observe a collection of query results. You
can perform a quick write to an ObservedResults collection, and the view
automatically updates itself when the observed query changes. For example,
you can remove a dog from an observed list of dogs using `onDelete`.

> Note:
> The `@ObservedResults` property wrapper is intended for use in a
SwiftUI View. If you want to observe results in a view model, register
a change listener.
>

```swift
struct DogsView: View {
    @ObservedResults(Dog.self) var dogs

    /// The button to be displayed on the top left.
    var leadingBarButton: AnyView?

    var body: some View {
        NavigationView {
            VStack {
                // The list shows the dogs in the realm.
                // The ``@ObservedResults`` above implicitly opens a realm and retrieves
                // all the Dog objects. We can then pass those objects to views further down the
                // hierarchy.
                List {
                    ForEach(dogs) { dog in
                        DogRow(dog: dog)
                    }.onDelete(perform: $dogs.remove)
                }.listStyle(GroupedListStyle())
                    .navigationBarTitle("Dogs", displayMode: .large)
                    .navigationBarBackButtonHidden(true)
                    .navigationBarItems(
                        leading: self.leadingBarButton,
                        // Edit button on the right to enable rearranging items
                        trailing: EditButton())
            }.padding()
        }
    }
}

```

> Seealso:
> For more information about the query syntax and types of queries that Realm
supports, see: Read and Filter
Data.
>

### Sort Observed Results
The `@ObservedResults`
property wrapper can take a `SortDescriptor` parameter to sort the query results.

```swift
struct SortedDogsView: View {
    @ObservedResults(Dog.self,
                     sortDescriptor: SortDescriptor(keyPath: "name",
                        ascending: true)) var dogs

    var body: some View {
        NavigationView {
            // The list shows the dogs in the realm, sorted by name
            List(dogs) { dog in
                DogRow(dog: dog)
            }
        }
    }
}

```

> Tip:
> You cannot use a computed property as a `SortDescriptor` for `@ObservedResults`.
>

### Observe Sectioned Results
> Version added: 10.29.0

You can observe a results set that is divided into sections by a key
generated from a property on the object. We've added a computed variable
to the model that we don't persist; we just use this to section the results
set.

```swift
var firstLetter: String {
    guard let char = name.first else {
        return ""
    }
    return String(char)
}

```

Then, we can use the `@ObservedSectionedResults` property wrapper to
observe the results set divided into sections based on the computed variable
key.

```swift
@ObservedSectionedResults(Dog.self,
                          sectionKeyPath: \.firstLetter) var dogs

```

You might use these observed sectioned results to populate a List view
divided by sections:

```swift
struct SectionedDogsView: View {
    @ObservedSectionedResults(Dog.self,
                              sectionKeyPath: \.firstLetter) var dogs

    /// The button to be displayed on the top left.
    var leadingBarButton: AnyView?

    var body: some View {
        NavigationView {
            VStack {
                // The list shows the dogs in the realm, split into sections according to the keypath.
                List {
                    ForEach(dogs) { section in
                        Section(header: Text(section.key)) {
                            ForEach(section) { dog in
                                DogRow(dog: dog)
                            }
                        }
                    }
                }
                .listStyle(GroupedListStyle())
                    .navigationBarTitle("Dogs", displayMode: .large)
                    .navigationBarBackButtonHidden(true)
                    .navigationBarItems(
                        leading: self.leadingBarButton,
                        // Edit button on the right to enable rearranging items
                        trailing: EditButton())
            }.padding()
        }
    }
}

```

---

### Guides Swiftui Swiftui Previews (`docs/guides/swiftui/swiftui-previews.md`)

# Use Realm with SwiftUI Previews
## Overview
SwiftUI Previews are a useful tool during development. You can work with Realm
data in SwiftUI Previews in a few ways:

- Initialize individual objects to use in detail views
- Conditionally use an array of objects in place of `@ObservedResults`
- Create a realm that contains data for the previews

SwiftUI Preview debugging can be opaque, so we also have a few tips to debug
issue with persisting Realms within SwiftUI Previews.

### Initialize an Object for a Detail View
In the simplest case, you can use SwiftUI Previews with one or more objects
that use Realm properties you can set directly at initialization.
You might want to do this when previewing a Detail view. Consider DoggoDB's
`DogDetailView`:

```swift
struct DogDetailView: View {
    @ObservedRealmObject var dog: Dog

    var body: some View {
        VStack {
            Text(dog.name)
                .font(.title2)
            Text("\(dog.name) is a \(dog.breed)")
            AsyncImage(url: dog.profileImageUrl) { image in
                            image.resizable()
                        } placeholder: {
                            ProgressView()
                        }
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 150, height: 150)
            Text("Favorite toy: \(dog.favoriteToy)")
        }
    }
}

```

Create an extension for your model object. Where you put this extension depends
on convention in your codebase. You may put it directly in the model file,
have a dedicated directory for sample data, or use some other convention in
your codebase.

In this extension, initialize one or more Realm objects with `static let`:

```swift
extension Dog {
    static let dog1 = Dog(value: ["name": "Lita", "breed": "Lab mix", "weight": 27, "favoriteToy": "Squeaky duck", "profileImageUrl": "https://www.corporaterunaways.com/images/2021/04/lita-768x768.jpeg"])
    static let dog2 = Dog(value: ["name": "Maui", "breed": "English Springer Spaniel", "weight": 42, "favoriteToy": "Wubba", "profileImageUrl": "https://www.corporaterunaways.com/images/2021/04/maui_with_leaf-768x576.jpeg"])
    static let dog3 = Dog(value: ["name": "Ben", "breed": "Border Collie mix", "weight": 48, "favoriteToy": "Frisbee", "profileImageUrl": "https://www.corporaterunaways.com/images/2012/03/ben-630x420.jpg"])

}

```

In this example, we initialize objects with a value. You can only initialize objects with
a value when your model contains properties that you can directly initialize.
If your model object contains properties that are only mutable within a
write transaction, such as a List property,
you must instead create a realm to use with your SwiftUI Previews.

After you have initialized an object as an extension of your model class,
you can use it in your SwiftUI Preview. You can pass the object directly
to the View in the Preview:

```swift
struct DogDetailView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            DogDetailView(dog: Dog.dog1)
        }
    }
}

```

### Conditionally Use ObservedResults in a List View
When you use `@ObservedResults`
in a List view, this implicitly opens a realm and queries it. For this to
work in a Preview, you need a realm populated with data. As an alternative, you can conditionally
use a static array in Previews and only use the `@ObservedResults` variable
when running the app.

You could do this in multiple ways, but for the sake of making our
code easier to read and understand, we'll create an `EnvironmentValue`
that can detect whether the app is running in a Preview:

```swift
import Foundation
import SwiftUI

public extension EnvironmentValues {
   var isPreview: Bool {
      #if DEBUG
      return ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
      #else
      return false
      #endif
   }
}
```

Then, we can use this as an environment value in our view, and conditionally
change which variable we use based on whether or not we are in a Preview.

This example builds on the Dog extension we defined above. We'll create an `dogArray` as
a `static let` in our Dog extension, and include the item objects we
already created:

```swift
static let dogArray = [dog1, dog2, dog3]
```

Then, when we iterate through our List, use the static `dogArray` if
running in a Preview, or use the `@ObservedResults` query if not in a Preview.

```swift
struct DogsView: View {
   @Environment(\.isPreview) var isPreview
   @ObservedResults(Dog.self) var dogs
   var previewDogs = Dog.dogArray

   var body: some View {
      NavigationView {
         VStack {
            List {
               if isPreview {
                  ForEach(previewDogs) { dog in
                     DogRow(dog: dog)
                  }
               } else {
                  ForEach(dogs) { dog in
                     DogRow(dog: dog)
                  }.onDelete(perform: $dogs.remove)
               }
            }
            ... More View code
```

This has the benefit of being lightweight and not persisting any data, but
the downside of making the View code more verbose. If you prefer cleaner
View code, you can create a realm with data that you use in the Previews.

### Create a Realm with Data for Previews
In some cases, your only option to see realm data in a SwiftUI Preview
is to create a realm that contains the data. You might do this when populating
a property that can only be populated during a write transaction, rather
than initialized directly with a value, such as a List or MutableSet.
You might also want to do this if your view relies on more complex object
hierarchies being passed in from other views.

However, using a realm directly does inject state into your SwiftUI Previews,
which can come with drawbacks. Whether you're using Realm or Core Data,
stateful SwiftUI Previews can cause issues like:

- Seeing unexpected or duplicated data due to re-running the realm file
creation steps repeatedly
- Needing to perform a migration within the SwiftUI Preview when you make model changes
- Potential issues related to changing state within views
- Unexplained crashes or performance issues related to issues that are not
surfaced in a visible way in SwiftUI Previews

You can avoid or fix some of these issues with these tips:

- Use an in-memory realm, when possible (demonstrated in the example above)
- Manually delete all preview data from the command line to reset state
- Check out diagnostic logs to try to troubleshoot SwiftUI Preview issues

You can create a static variable for your realm in your model extension.
This is where you do the work to populate your realm. In our case, we
create a `Person` and append some `Dog` objects to the `dogs`
List property. This example builds on the example above where we initialized
a few Dog objects in an Dog extension.

We'll create a `Person` extension, and create a single `Person` object
in that extension. Then, we'll create a `previewRealm` by adding the
`Person` we just created, and appending the example `Dog` objects from
the `Dog` extension.

To avoid adding these objects more than once, we add a check to see if the
Person already exists by querying for Person objects and checking that
the count is 1. If the realm contains a Person, we can use it in our
SwiftUI Preview. If not, we add the data.

```swift
static var previewRealm: Realm {
    var realm: Realm
    let identifier = "previewRealm"
    let config = Realm.Configuration(inMemoryIdentifier: identifier)
    do {
        realm = try Realm(configuration: config)
        // Check to see whether the in-memory realm already contains a Person.
        // If it does, we'll just return the existing realm.
        // If it doesn't, we'll add a Person append the Dogs.
        let realmObjects = realm.objects(Person.self)
        if realmObjects.count == 1 {
            return realm
        } else {
            try realm.write {
                realm.add(person)
                person.dogs.append(objectsIn: [Dog.dog1, Dog.dog2, Dog.dog3])
            }
            return realm
        }
    } catch let error {
        fatalError("Can't bootstrap item data: \(error.localizedDescription)")
    }
}

```

To use it in the SwiftUI Preview, our ProfileView code expects a Profile.
This is a projection of the Person object. In our
Preview, we can get the realm, query it for the Profile, and pass it to the
view:

```swift
struct ProfileView_Previews: PreviewProvider {
    static var previews: some View {
        let realm = Person.previewRealm
        let profile = realm.objects(Profile.self)
        ProfileView(profile: profile.first!)
    }
}

```

If you don't have a View that is expecting a realm object to be passed in,
but instead uses `@ObservedResults` to query a realm or otherwise work
with an existing realm, you can inject the realm into the view as an
environment value:

```swift
struct SomeListView_Previews: PreviewProvider {
   static var previews: some View {
      SomeListView()
         .environment(\.realm, Person.previewRealm)
   }
}
```

#### Use an In-Memory Realm
When possible, use an in-memory realm
to get around some of the state-related issues that can come from using
a database within a SwiftUI Preview.

Use the `inMemoryIdentifier`
configuration property when you initialize the realm.

```swift
static var previewRealm: Realm {
   var realm: Realm
   let identifier = "previewRealm"
   let config = Realm.Configuration(inMemoryIdentifier: identifier)
   do {
      realm = try Realm(configuration: config)
      // ... Add data to realm
```

> Note:
> Do not use the the `deleteRealmIfMigrationNeeded`
configuration property when you initialize a realm for SwiftUI Previews.
Due to the way Apple has implemented SwiftUI Previews, using this property
to bypass migration issues causes SwiftUI Previews to crash.
>

#### Delete SwiftUI Previews
If you run into other SwiftUI Preview issues related to state,
such as a failure to load a realm in a Preview due to migration being
required, there are a few things you can do to remove cached Preview data.

The Apple-recommended fix is to close Xcode and use the command line to
delete all your existing SwiftUI Preview data.

1. Close Xcode.
2. From your command line, run: `xcrun simctl --set previews delete all`

It's possible that data may persist after running this command. This is
likely due to Xcode retaining a reference due to something in the Preview
and being unable to delete it. You can also try these steps to resolve issues:

- Build for a different simulator
- Restart the computer and re-run `xcrun simctl --set previews delete all`
- Delete stored Preview data directly. This data is stored in
`~/Library/Developer/Xcode/UserData/Previews`.

#### Get Detailed Information about SwiftUI Preview Crashes
If you have an unexplained SwiftUI Preview crash when using realm, first try
running the application on the simulator. The error messaging and logs available
for the simulator make it easier to find and diagnose issues. If you can
debug the issue in the simulator, this is the easiest route.

If you cannot replicate a SwiftUI Preview crash in the simulator, you can
view crash logs for the SwiftUI Preview app. These logs are available in
`~/Library/Logs/DiagnosticReports/`. These logs sometimes appear after
a delay, so wait a few minutes after a crash if you don't see the relevant
log immediately.

---

### Guides Swiftui Swiftui Tutorial (`docs/guides/swiftui/swiftui-tutorial.md`)

# Realm with SwiftUI QuickStart
## Prerequisites
- Have Xcode 12.4 or later (minimum Swift version 5.3.1).
- Create a new Xcode project using the SwiftUI "App" template with a minimum iOS target of 15.0.
- Install the Swift SDK. This SwiftUI app requires a minimum
SDK version of 10.19.0.

## Overview
> Seealso:
> This page provides a small working app to get you up and running with
Realm and SwiftUI quickly. If you'd like to see additional examples,
including more explanation about Realm's SwiftUI features, see:
SwiftUI.
>

This page contains all of the code for a working Realm and SwiftUI app.
The app starts on the `ItemsView`, where you can edit a list of items:

- Press the `Add` button on the bottom right of the screen to add
randomly-generated items.
- Press the `Edit` button on the top right to modify the list order,
which the app persists in the realm.
- You can also swipe to delete items.

When you have items in the list, you can press one of the items to
navigate to the `ItemDetailsView`. This is where you can modify the
item name or mark it as a favorite:

- Press the text field in the center of the screen and type a new name.
When you press Return, the item name should update across the app.
- You can also toggle its favorite status by pressing the heart toggle in the
top right.

### Get Started
We assume you have created an Xcode project with the SwiftUI "App"
template. Open the main Swift file and delete all of the code inside,
including any `@main` `App` classes that Xcode generated for you. At
the top of the file, import the Realm and SwiftUI frameworks:

```swift
import RealmSwift
import SwiftUI

```

> Tip:
> Just want to dive right in with the complete code? Jump to
Complete Code below.
>

### Define Models
A common Realm data modeling use case is to have "things" and
"containers of things". This app defines two related Realm object models: item
and itemGroup.

An item has two user-facing properties:

- A randomly generated-name, which the user can edit.
- An `isFavorite` boolean property, which shows whether the user "favorited"
the item.

An itemGroup contains items. You can extend the itemGroup to have a name and an
association with a specific user, but that's out of scope of this guide.

Paste the following code into your main Swift file to define the models:

```
/* Detailed source-code truncated for AI context efficiency. */
```

### Views and Observed Objects
The entrypoint of the app is the `ContentView` class that derives from
`SwiftUI.App`. For now, this always displays the
`LocalOnlyContentView`.

```swift
@main
struct ContentView: SwiftUI.App {
    var body: some Scene {
        WindowGroup {
            LocalOnlyContentView()
        }
    }
}

```

> Tip:
> You can use a realm other than the default realm by passing
an environment object from higher in the View hierarchy:
>
> ```swift
> LocalOnlyContentView()
>   .environment(\.realmConfiguration, Realm.Configuration( /* ... */ ))
> ```
>

The LocalOnlyContentView has an `@ObservedResults` itemGroups. This implicitly uses the default
realm to load all itemGroups when the view appears.

This app only expects there to ever be one itemGroup. If there is an itemGroup
in the realm, the LocalOnlyContentView renders an `ItemsView` for
that itemGroup.

If there is no itemGroup already in the realm, then the
LocalOnlyContentView displays a ProgressView while it adds one. Because
the view observes the itemGroups thanks to the `@ObservedResults` property
wrapper, the view immediately refreshes upon adding that first itemGroup and
displays the ItemsView.

```swift
/// The main content view
struct LocalOnlyContentView: View {
    @State var searchFilter: String = ""
    // Implicitly use the default realm's objects(ItemGroup.self)
    @ObservedResults(ItemGroup.self) var itemGroups

    var body: some View {
        if let itemGroup = itemGroups.first {
            // Pass the ItemGroup objects to a view further
            // down the hierarchy
            ItemsView(itemGroup: itemGroup)
        } else {
            // For this small app, we only want one itemGroup in the realm.
            // You can expand this app to support multiple itemGroups.
            // For now, if there is no itemGroup, add one here.
            ProgressView().onAppear {
                $itemGroups.append(ItemGroup())
            }
        }
    }
}

```

> Tip:
> Starting in SDK version 10.12.0, you can use an optional key path parameter
with `@ObservedResults` to filter change notifications to only those
occurring on the provided key path or key paths. For example:
>
> ```
> @ObservedResults(MyObject.self, keyPaths: ["myList.property"])
> ```
>

The ItemsView receives the itemGroup from the parent view and stores it in
an `@ObservedRealmObject`
property. This allows the ItemsView to "know" when the object has
changed regardless of where that change happened.

The ItemsView iterates over the itemGroup's items and passes each item to an
`ItemRow` for rendering as a list.

To define what happens when a user deletes or moves a row, we pass the
`remove` and `move` methods of the Realm
`List` as the handlers of the respective
remove and move events of the SwiftUI List. Thanks to the
`@ObservedRealmObject` property wrapper, we can use these methods
without explicitly opening a write transaction. The property wrapper
automatically opens a write transaction as needed.

```
/* Detailed source-code truncated for AI context efficiency. */
```

Finally, the `ItemRow` and `ItemDetailsView` classes use the
`@ObservedRealmObject` property wrapper with the item passed in from
above. These classes demonstrate a few more examples of how to use the
property wrapper to display and update properties.

```swift
/// Represents an Item in a list.
struct ItemRow: View {
    @ObservedRealmObject var item: Item

    var body: some View {
        // You can click an item in the list to navigate to an edit details screen.
        NavigationLink(destination: ItemDetailsView(item: item)) {
            Text(item.name)
            if item.isFavorite {
                // If the user "favorited" the item, display a heart icon
                Image(systemName: "heart.fill")
            }
        }
    }
}

/// Represents a screen where you can edit the item's name.
struct ItemDetailsView: View {
    @ObservedRealmObject var item: Item

    var body: some View {
        VStack(alignment: .leading) {
            Text("Enter a new name:")
            // Accept a new name
            TextField("New name", text: $item.name)
                .navigationBarTitle(item.name)
                .navigationBarItems(trailing: Toggle(isOn: $item.isFavorite) {
                    Image(systemName: item.isFavorite ? "heart.fill" : "heart")
                })
        }.padding()
    }
}

```

> Tip:
> `@ObservedRealmObject` is a frozen object. If you want to modify
the properties of an `@ObservedRealmObject`
directly in a write transaction, you must `.thaw()` it first.
>

At this point, you have everything you need to work with
Realm and SwiftUI. Test it out and see if everything is
working as expected.

## Complete Code
If you would like to copy and paste or examine the complete code, see below.

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### Guides Swiftui Write (`docs/guides/swiftui/write.md`)

# Write Data - SwiftUI
## Perform a Quick Write
In addition to performing writes inside a transaction block, the Realm Swift
SDK offers a convenience feature to enable quick writes without explicitly
performing a write transaction.

When you use the `@ObservedRealmObject` or `@ObservedResults` property
wrappers, you can implicitly open a write transaction. Use the `$` operator
to create a two-way binding to the state object. Then, when you make changes
to the bound object or collection, you initiate an implicit write.

The Realm SwiftUI property wrappers work with frozen data to provide thread safety. When you use `$` to
create a two-way binding, the Realm Swift SDK manages thawing the
frozen objects so you can write to them.

### Update an Object's Properties
In this example, we create a two-way binding with one of the state object's
properties. `$dog.favoriteToy` creates a binding to the model Dog
object's `favoriteToy` property

When the app user updates that field in this example, Realm
opens an implicit write transaction and saves the new value to the database.

```swift
struct EditDogDetails: View {
    @ObservedRealmObject var dog: Dog
    
    var body: some View {
        VStack {
            Text(dog.name)
                .font(.title2)
            TextField("Favorite toy", text: $dog.favoriteToy)
        }
    }
}

```

### Add or Remove Objects in an ObservedResults Collection
While a regular Realm Results collection
is immutable, `ObservedResults`
is a mutable collection that allows you to perform writes using a two-way
binding. When you update the bound collection, Realm opens an implicit write
transaction and saves the changes to the collection.

In this example, we remove an element from the results set using
`$dogs.remove` in the `onDelete`. Using the `$dogs` here creates a
two-way binding to a `BoundCollection` that lets us mutate the
`@ObservedResults` `dogs` collection.

We add an item to the results using `$dogs.append` in the
`addDogButton`.

These actions write directly to the `@ObservedResults` collection.

```
/* Detailed source-code truncated for AI context efficiency. */
```

> Note:
> The `@ObservedResults` property wrapper is intended for use in a
SwiftUI View. If you want to observe results in a view model, register
a change listener.
>

### Append an Object to a List
When you have a two-way binding with an `@ObservedRealmObject` that has
a list property, you can add new objects to the list.

In this example, the `Person` object has a list property that forms a
to-many relationship with one or more dogs.

```swift
class Person: Object, ObjectKeyIdentifiable {
   @Persisted(primaryKey: true) var _id: ObjectId
   @Persisted var firstName = ""
   @Persisted var lastName = ""
   ...
   @Persisted var dogs: List<Dog>
}
```

When the user presses the `Save` button, this:

- Creates a `Dog` object with the details that the user has entered
- Appends the `Dog` object to the `Person` object's `dogs` list

```swift
struct AddDogToPersonView: View {
    @ObservedRealmObject var person: Person
    @Binding var isInAddDogView: Bool
    @State var name = ""
    @State var breed = ""
    @State var weight = 0
    @State var favoriteToy = ""
    @State var profileImageUrl: URL?

    var body: some View {
        Form {
            TextField("Dog's name", text: $name)
            TextField("Dog's breed", text: $breed)
            TextField("Dog's weight", value: $weight, format: .number)
            TextField("Dog's favorite toy", text: $favoriteToy)
            TextField("Image link", value: $profileImageUrl, format: .url)
                            .keyboardType(.URL)
                            .textInputAutocapitalization(.never)
                            .disableAutocorrection(true)
            Section {
                Button(action: {
                    let dog = createDog(name: name, breed: breed, weight: weight, favoriteToy: favoriteToy, profileImageUrl: profileImageUrl)
                    $person.dogs.append(dog)
                    isInAddDogView.toggle()
                }) {
                    Text("Save")
                }
                Button(action: {
                    isInAddDogView.toggle()
                }) {
                    Text("Cancel")
                }
            }
        }
    }
}
```

### Use Create to Copy an Object Into the Realm
There may be times when you create a new object, and set one of its properties
to an object that already exists in the realm. Then, when you go to add the
new object to the realm, you see an error similar to:

```shell
Object is already managed by another Realm. Use create instead to copy it into this Realm.
```

When this occurs, you can use the `.create`
method to initialize the object, and use `modified: .update` to set its
property to the existing object.

> Example:
> Consider a version of the DoggoDB `Dog` model where the `favoriteToy`
property isn't just a `String`, but is an optional `DogToy` object:
>
> ```swift
> class Dog: Object, ObjectKeyIdentifiable {
>    @Persisted(primaryKey: true) var _id: UUID
>    @Persisted var name = ""
>    ...
>    @Persisted var favoriteToy: DogToy?
>    ...
> }
> ```
>
> When your app goes to create a new `Dog` object, perhaps it checks to see
if the `DogToy` already exists in the realm, and then set the `favoriteToy`
property to the existing dog toy.
>
> When you go to append the new `Dog` to the `Person` object, you may
see an error similar to:
>
> ```shell
> Object is already managed by another Realm. Use create instead to copy it into this Realm.
> ```
>
> The `Dog` object remains unmanaged until you append it to the `Person`
object's `dogs` property. When the Realm Swift SDK checks the `Dog`
object to find the realm that is currently managing it, it finds nothing.
>
> When you use the `$` notation to perform a quick write that appends the
`Dog` object to the `Person` object, this write uses the realm it has
access to in the view. This is a realm instance implicitly opened by
the `@ObservedRealmObject` or `@ObservedResults` property wrapper.
The existing `DogToy` object, however, may be managed by a different
realm instance.
>
> To solve this error, use the `.create`
method when you initialize the `Dog` object, and use
`modified: .update` to set its `favoriteToy` value to the existing
object:
>
> ```swift
> // When working with an `@ObservedRealmObject` `Person`, this is a frozen object.
> // Thaw the object and get its realm to perform the write to append the new dog.
> let thawedPersonRealm = frozenPerson.thaw()!.realm!
> try! thawedPersonRealm.write {
>     // Use the .create method with `update: .modified` to copy the
>     // existing object into the realm
>     let dog = thawedPersonRealm.create(Dog.self, value:
>                                         ["name": "Maui",
>                                          "favoriteToy": wubba],
>                                        update: .modified)
>     person.dogs.append(dog)
> }
>
> ```
>

## Perform an Explicit Write
In some cases, you may want or need to explicitly perform a write transaction
instead of using the implicit `$` to perform a quick write. You may want
to do this when:

- You need to look up additional objects to perform a write
- You need to perform a write to objects you don't have access to in the view

If you pass an object you are observing with `@ObservedRealmObject` or
`@ObservedResults` into a function where you perform an explicit write
transaction that modifies the object, you must thaw it first.

```swift
let thawedCompany = company.thaw()!

```

You can access the realm that is managing the object or objects by calling
`.realm` on the object or collection:

```swift
let realm = company.realm!.thaw()

```

Because the SwiftUI property wrappers use frozen objects, you must thaw
the realm before you can write to it.

> Example:
> Consider a version of the DoggoDB app where a `Company` object
has a list of `Employee` objects. Each `Employee` has a list of
`Dog` objects. But for business reasons, you also wanted to have a
list of `Dog` objects available directly on the `Company` object,
without being associated with an `Employee`. The model might look
something like:
>
> ```swift
> class Company: Object, ObjectKeyIdentifiable {
>     @Persisted(primaryKey: true) var _id: ObjectId
>     @Persisted var companyName = ""
>     @Persisted var employees: List<Employee>
>     @Persisted var dogs: List<Dog>
> }
>
> ```
>
> Consider a view where you have access to the `Company` object, but
want to perform an explicit write to add an existing dog to an existing
employee. Your function might look something like:
>
> ```swift
> // The `frozenCompany` here represents an `@ObservedRealmObject var company: Company`
> performAnExplicitWrite(company: frozenCompany, employeeName: "Dachary", dogName: "Maui")
>
> func performAnExplicitWrite(company: Company, employeeName: String, dogName: String) {
>     // Get the realm that is managing the `Company` object you passed in.
>     // Thaw the realm so you can write to it.
>     let realm = company.realm!.thaw()
>     // Thawing the `Company` object that you passed in also thaws the objects in its List properties.
>     // This lets you append the `Dog` to the `Employee` without individually thawing both of them.
>     let thawedCompany = company.thaw()!
>     let thisEmployee = thawedCompany.employees.where { $0.name == employeeName }.first!
>     let thisDog = thawedCompany.dogs.where { $0.name == dogName }.first!
>     try! realm.write {
>         thisEmployee.dogs.append(thisDog)
>     }
> }
>
> ```
>

---

### Guides Swiftui Model Data Change An Object Model (`docs/guides/swiftui/model-data/change-an-object-model.md`)

# Change an Object Model - SwiftUI
## Overview
When you update your object schema, you must increment the schema version
and perform a migration. You might update your object schema between major
version releases of your app.

For information on how to actually perform the migration, see:
Change an Object Model.

This page focuses on how to use migrated data in SwiftUI Views.

## Use Migrated Data with SwiftUI
To perform a migration:

- Update your schema and write a migration block, if required
- Specify a `Realm.Configuration`
that uses this migration logic and/or updated schema version when you
initialize your realm.

From here, you have a few options to pass the configuration object. You can:

- Set the configuration as the default configuration. If you do not explicitly pass the
configuration via environment injection or as a parameter, property
wrappers use the default configuration.
- Use environment injection to provide this configuration to the first view
in your hierarchy that uses Realm
- Explicitly provide the configuration to a Realm property wrapper that takes
a configuration object, such as `@ObservedResults` or `@AsyncOpen`.

> Example:
> For example, you might want to add a property to an existing object. We
could add a `favoriteTreat` property to the `Dog` object in DoggoDB:
>
> ```swift
> @Persisted var favoriteTreat = ""
> ```
>
> After you add your new property to the schema, you must increment the
schema version. Your `Realm.Configuration` might look like this:
>
> ```swift
> let config = Realm.Configuration(schemaVersion: 2)
>
> ```
>
> Declare this configuration somewhere that is accessible to the first view
in the hierarchy that needs it. Declaring this above your `@main` app
entrypoint makes it available everywhere, but you could also put it in
the file where you first open a realm.
>

### Set a Default Configuration
You can set a default configuration in a SwiftUI app the same as any other
Realm Swift app. Set the default realm configuration by assigning a new
Realm.Configuration instance to the `Realm.Configuration.defaultConfiguration`
class property.

```swift
// Open the default realm
let defaultRealm = try! Realm()

// Open the realm with a specific file URL, for example a username
let username = "GordonCole"
var config = Realm.Configuration.defaultConfiguration
config.fileURL!.deleteLastPathComponent()
config.fileURL!.appendPathComponent(username)
config.fileURL!.appendPathExtension("realm")
let realm = try! Realm(configuration: config)

```

### Pass the Configuration Object as an Environment Object
Once you have declared the configuration, you can inject it as an environment
object to the first view in your hierarchy that opens a realm. If you are
using the `@ObservedResults` or `@ObservedRealmObject` property wrappers,
these views implicitly open a realm, so they also need access to this
configuration.

```swift
.environment(\.realmConfiguration, config)
```

You can pass the realm configuration environment object directly
to the `LocalOnlyContentView`:

```swift
.environment(\.realmConfiguration, config)

```

Which opens a realm implicitly with:

```swift
struct LocalOnlyContentView: View {
    // Implicitly use the default realm's objects(Dog.self)
    @ObservedResults(Dog.self) var dogs

    var body: some View {
        if dogs.first != nil {
            // If dogs exist, go to the DogsView
            DogsView()
        } else {
            // If there is no Dog object, add one here.
            AddDogView()
        }
    }
}

```

### Explicitly Pass the Updated Configuration to a Realm SwiftUI Property Wrapper
You can explicitly pass the configuration object to a Realm SwiftUI
property wrapper that takes a configuration object, such as `@ObservedResults`
or `@AutoOpen`. In this case, you might pass it directly to `@ObservedResults`
in our `DogsView`.

```swift
// Use a `config` that you've passed in from above.
@ObservedResults(Dog.self, configuration: config) var dogs
```

---

### Guides Swiftui Model Data Define A Realm Object Model (`docs/guides/swiftui/model-data/define-a-realm-object-model.md`)

# Realm Object Models - SwiftUI
## Concepts: Object Models and Relationships
Modeling data for SwiftUI builds on the same object model and relationship
concepts in the Swift SDK. If you are unfamiliar with Realm Swift SDK
data modeling concepts, see: Define a Realm Object Model - Swift SDK.

## Binding the Object Model to the UI
The Model-View-ViewModel (MVVM) design pattern advocates creating a view
model that abstracts the model from the View code. While you can certainly
do that with Realm, the Swift SDK provides tools that make it easy to
work directly with your data in SwiftUI Views. These tools include things
like:

- Property wrappers that create bindings to underlying observable objects
- A class to project and transform underlying model objects for use in
specific views

## Transforming Data for SwiftUI Views
The Realm Swift SDK provides a special type of object, called a `Projection`, to transform
and work with subsets of your data. Consider a projection similar to
a view model. It lets you pass through or transform the original
object's properties in different ways:

- Passthrough: The projection's property has the same name and type as
the original object.
- Rename: The projection's property has the same type as the original object,
but a different name.
- Keypath resolution: Use this to access specific properties of the
projected Object.
- Collection mapping: You can map some collection types to a collection of primitive values.
- Exclusion: All properties of the original Realm object not defined in
the projection model. Any changes to those properties do not trigger a
change notification when observing the projection.

When you use a Projection, you get all the benefits of Realm's
live objects:

- The class-projected object live updates
- You can observe it for changes
- You can apply changes directly to the properties in write transactions

## Define a New Object
You can define a Realm object by deriving from the
`Object` or
`EmbeddedObject`
class. The name of the class becomes the table name in the realm,
and properties of the class persist in the database. This makes it
as easy to work with persisted objects as it is to work with
regular Swift objects.

The Realm SwiftUI documentation uses a model for a fictional app,
DoggoDB. This app is a company directory of employees who have dogs. It
lets people share a few details about their dogs with other employees.

The data model includes a Person object, with a to-many
relationship to that person's Dog objects.
It also uses a special Realm Swift SDK data type, `PersistableEnum`, to store information
about the person's business unit.

```swift
class Person: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var firstName = ""
    @Persisted var lastName = ""
    @Persisted var personId = ""
    @Persisted var company = "my business"
    @Persisted var businessUnit = BusinessUnitEnum.engineering
    @Persisted var profileImageUrl: URL?
    @Persisted var dogs: List<Dog>
}

enum BusinessUnitEnum: String, PersistableEnum, CaseIterable {
    case customerEngineering = "Customer Engineering"
    case educationCommunityAndDocs = "Education, Community and Docs"
    case engineering = "Engineering"
    case financeAndOperations = "Finance and Operations"
    case humanResourcesAndRescruiting = "Human Resources and Recruiting"
    case management = "Management"
    case marketing = "Marketing"
    case product = "Product"
    case sales = "Sales"
}

class Dog: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: UUID
    @Persisted var name = ""
    @Persisted var breed = ""
    @Persisted var weight = 0
    @Persisted var favoriteToy = ""
    @Persisted var profileImageUrl: URL?
    @Persisted var dateLastUpdated = Date()
    @Persisted(originProperty: "dogs") var person: LinkingObjects<Person>
    var firstLetter: String {
        guard let char = name.first else {
            return ""
        }
        return String(char)
    }
}

```

> Seealso:
> For complete details about defining a Realm object model, see:
>
> - Object Models
> - Relationships
> - Supported Data Types
>

## Define a Projection
Our fictional DoggoDB app has a user Profile view. This view displays
some details about the person, but we don't need all of the properties
of the `Person` model. We can create a `Projection` with only the details we want. We can also modify
the `lastName` property to use just the first initial of the last name.

```swift
class Profile: Projection<Person> {
    @Projected(\Person.firstName) var firstName // Passthrough from original object
    @Projected(\Person.lastName.localizedCapitalized.first) var lastNameInitial // Access and transform the original property
    @Projected(\Person.personId) var personId
    @Projected(\Person.businessUnit) var businessUnit
    @Projected(\Person.profileImageUrl) var profileImageUrl
    @Projected(\Person.dogs) var dogs
}

```

We can use this projection in the Profile view instead of the original
`Person` object.

Class projection works with SwiftUI property wrappers:

- `ObservedRealmObject`
- `ObservedResults`

> Seealso:
> For a complete example of using a class projection in a SwiftUI
application, see [the Projections example app](https://github.com/realm/realm-cocoa/tree/master/examples#projections).
>

---

--- METRICS ---
- Files Extracted: 43
- Estimated Token Budget: ~100609 tokens
- Canonical Reference: https://codewiki.google/github.com/realm/realm-swift
