Docs Menu
Docs Home
/ /
Atlas Device SDKs
/ /

Define a Realm Object Model - Swift SDK

On this page

  • Define a New Object Type
  • Declare Properties
  • Persisted Property Attributes
  • Objective-C Dynamic Property Attributes
  • Specify an Optional/Required Property
  • Specify a Primary Key
  • Index a Property
  • Ignore a Property
  • Declare Enum Properties
  • Remap a Property Name
  • Define a Class Projection
  • About These Examples
  • How to Define a Class Projection
  • Define an Asymmetric Object


Class names are limited to a maximum of 57 UTF-8 characters.

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.

New in version 10.10.0: The @Persisted declaration style replaces the @objc dynamic, RealmOptional, and RealmProperty declaration notations from older versions of the SDK. For an older version of the SDK, see: Objective-C Dynamic Property Attributes.

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.


See also:

Our Supported Property Types page contains a property declaration cheatsheet.

Changed in version 10.10.0: This 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.

Changed in version 10.8.0: RealmProperty replaces RealmOptional


See also:

Our Supported Property Types page contains a property declaration cheatsheet.


For reference on which types Realm supports for use as properties, see Supported Property Types.


Property names are limited to a maximum of 63 UTF-8 characters.

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.

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.

New in version 10.8.0: UUID and AnyRealmValue types

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.


Realm automatically ignores read-only properties.

New in version 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. You might want to do this if your Device Sync schema property names use snake case, for example, while your project uses Swift-idiomatic camel case.

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. If we write to a synced realm, the Sync schema sees the values stored using the private property name first_name.

class Person: Object {
@Persisted var firstName = ""
@Persisted var lastName = ""
override class public func propertiesMapping() -> [String: String] {
["firstName": "first_name",
"lastName": "last_name"]

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:

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 = ""

New in version 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.


When you use a List or a MutableSet in a class projection, the type in the class projection should be ProjectedCollection.

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.

New in version 10.29.0.

If your app uses Flexible Sync, you can use Data Ingest to sync an object unidirectionally from your device to the database linked to your Atlas App Services App. Define an asymmetric object by inheriting from AsymmetricObject.

class WeatherSensor: AsymmetricObject {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var deviceId: String
@Persisted var temperatureInFahrenheit: Float
@Persisted var barometricPressureInHg: Float
@Persisted var windSpeedInMph: Int

Changed in version 10.42.4: Asymmetric objects can link to non-embedded objects.

AsymmetricObject broadly supports the same property types as Object, with a few exceptions:

  • Asymmetric objects can only link to embedded objects
    • Object and List<Object> properties are not supported in Swift SDK versions 10.42.3 and earlier. In Swift SDK versions 10.42.4 and later, asymmetric objects can link to non-embedded objects.

    • EmbeddedObject and List<EmbeddedObject> are supported.

You cannot link to an AsymmetricObject from within an Object. Doing so throws an error.

Asymmetric objects do not function in the same way as other Realm Objects. You cannot:

  • Add an asymmetric object to a realm

  • Remove an asymmetric object from a realm

  • Query an asymmetric object

You can only create an Asymmetric object, which then syncs unidirectionally to the Atlas database linked to your App with Device Sync.

For more information, see: Create an Asymmetric Object.

← Model Data