Introduction

Realm JavaScript enables you to efficiently write your app’s model layer in a safe, persisted and fast way. It’s designed to work with React Native and Node.js.

Here’s an example using React Native:

// Define your models and their propertiesclassCar{}Car.schema={name:'Car',properties:{make:'string',model:'string',miles:'int',}};classPerson{}Person.schema={name:'Person',properties:{name:{type:'string'},cars:{type:'list',objectType:'Car'},picture:{type:'data',optional:true},// optional property}};// Get the default Realm with support for our objectsletrealm=newRealm({schema:[Car,Person]});// Create Realm objects and write to local storagerealm.write(()=>{letmyCar=realm.create('Car',{make:'Honda',model:'Civic',miles:1000,});myCar.miles+=20;// Update a property value});// Query Realm for all cars with a high mileageletcars=realm.objects('Car').filtered('miles > 1000');// Will return a Results object with our 1 carcars.length// => 1// Add another carrealm.write(()=>{letmyCar=realm.create('Car',{make:'Ford',model:'Focus',miles:2000,});});// Query results are updated in realtimecars.length// => 2

Getting Started

Installation

Follow the installation instructions below to install Realm JavaScript via npm, or see the source on GitHub.

Make sure your environment is set up to run React Native applications. Follow the React Native instructions for getting started.

Apps using Realm can target both iOS and Android.

React Native 0.20.0 and later is supported.

Make sure the React Native Package Manager (rnpm) is globally installed and up-to-date:

npm install -g rnpm

Installation

Create a new React Native project:

react-native init <project-name>

Change directories into the new project (cd <project-name>) and add the realm dependency:

npm install --save realm

Next, link your project to the realm native module.

React Native >= 0.31.0

react-native link realm

React Native < 0.31.0

rnpm link realm

Warning for Android: Depending on the version, rnpm may generate an invalid configuration, updating Gradle correctly (android/settings.gradle and android/app/build.gradle) but failing to add the Realm module. Confirm that react-native link has added the Realm module; if it has not, link manually to the library with the following steps:

These instructions install the Developer Edition of the Realm Node.js SDK. If you have downloaded the Professional Edition or Enterprise Edition, follow the installation instructions you received in email.

If you’re using a crash reporter (like Crashlytics or HockeyApp), make sure to enable log collection. Realm logs metadata information (but no user data) when throwing exceptions and in irrecoverable situations, and these messages can help debug when things go wrong.

Models

Realm data models are defined by the schema information passed into a Realm during initialization. The schema for an object consists of the object’s name and a set of properties each of which has a name and type as well as the objectType for object and list properties. You can also designate each property to be optional or to have a default value.

If you’d prefer your objects inherit from an existing class, you just need to define the schema on the object constructor and pass in the constructor when creating a realm:

classPerson{getageSeconds(){returnMath.floor((Date.now()-this.birthday.getTime()));}getage(){returnageSeconds()/31557600000;}}Person.schema=PersonSchema;// Note here we are passing in the `Person` constructorletrealm=newRealm({schema:[CarSchema,Person]});

Once you have defined your object models you can create and fetch objects from the realm:

realm.write(()=>{letcar=realm.create('Car',{make:'Honda',model:'Civic',miles:750,});// you can access and set all properties defined in your modelconsole.log('Car type is '+car.make+' '+car.model);car.miles=1500;});

When accessing object properties, you can access nested properties using normal property syntax:

realm.write(()=>{varnameString=person.car.name;person.car.miles=1100;// create a new Car by setting the property to valid JSONperson.van={make:'Ford',model:'Transit'};// set both properties to the same car instanceperson.car=person.van;});

List Properties

For list properties you must specify the property type as list as well as the objectType:

When accessing list properties a List object is returned. List has methods very similar to a regular JavaScript array. The big difference is that any changes made to a List are automatically persisted to the underlying Realm. Additionally, Lists belong to the underlying object they were acquired from - you can only get List instances by accessing a property from an owning object and they cannot be manually created.

letcarList=person.cars;// Add new cars to the listrealm.write(()=>{carList.push({make:'Honda',model:'Accord',miles:100});carList.push({make:'Toyota',model:'Prius',miles:200});});letsecondCar=carList[1].model;// access using an array index

Optional Properties

Properties can be declared as optional or non-optional by specifying the optional designator in your property definition:

constPersonSchema={name:'Person',properties:{name:{type:'string'},// required propertybirthday:{type:'date',optional:true},// optional property// object properties are always optionalcar:{type:'Car'},}};letrealm=newRealm({schema:[PersonSchema,CarSchema]});realm.write(()=>{// optional properties can be set to null or undefined at creationletcharlie=realm.create('Person',{name:'Charlie',birthday:newDate(1995,11,25),car:null,});// optional properties can be set to `null`, `undefined`,// or to a new non-null valuecharlie.birthday=undefined;charlie.car={make:'Honda',model:'Accord',miles:10000};});

As seen above object properties are always optional and do not need an optional designation. List properties cannot be declared as optional or set to null. You can set or initialize a list with an empty array to clear it.

Default Property Values

Default property values can be specified by setting the default designator in the property definition. To use a default value, leave the property unspecified during object creation.

constCarSchema={name:'Car',properties:{make:{type:'string'},model:{type:'string'},drive:{type:'string',default:'fwd'},miles:{type:'int',default:0}}};realm.write(()=>{// Since `miles` is left out it defaults to `0`, and since// `drive` is specified, it overrides the default valuerealm.create('Car',{make:'Honda',model:'Accord',drive:'awd'});});

Indexed Properties

You can add an indexed designator to a property definition to cause that property to be indexed. This is supported for int, string, and bool property types:

Indexing a property will greatly speed up queries where the property is compared for equality at the cost of slower insertions.

Primary Keys

You can specify the primaryKey property in an object model for string and int properties. Declaring a primary key allows objects to be looked up and updated efficiently and enforces uniqueness for each value. Once an object with a primary key has been added to a Realm the primary key cannot be changed.

Creating Objects

Nested Objects

If an object has object properties, values for those properties can be created recursively by specifying JSON values for each child property:

letrealm=newRealm({schema:[PersonSchema,CarSchema]});realm.write(()=>{realm.create('Person',{name:'Joe',// nested objects are created recursivelycar:{make:'Honda',model:'Accord',drive:'awd'},});});

Updating Objects

Typed Updates

You can update any object by setting its properties within a write transaction.

realm.write(()=>{car.miles=1100;});

Creating and Updating Objects With Primary Keys

If your model class includes a primary key, you can have Realm intelligently update or add objects based off of their primary key values. This is done by passing true as the third argument to the create method:

realm.write(()=>{// Create a book objectrealm.create('Book',{id:1,title:'Recipes',price:35});// Update book with new price keyed off the idrealm.create('Book',{id:1,price:55},true);});

In the example above, since an object already exists with the id value of 1 and we have passed in true for the third argument, the price property is updated rather than trying to create a new object. Since the name property is omitted the object retains the original value for this property. Note that when creating or updating objects with primary key properties the primary key must be specified.

Deleting Objects

Objects can be deleted by calling the delete method within a write transaction.

realm.write(()=>{// Create a book objectletbook=realm.create('Book',{id:1,title:'Recipes',price:35});// Delete the bookrealm.delete(book);// Delete multiple books by passing in a `Results`, `List`,// or JavaScript `Array`letallBooks=realm.objects('Book');realm.delete(allBooks);// Deletes all books});

Queries

Queries allow you to get objects of a single type from a Realm, with the option of filtering and sorting those results. All queries (including queries and property access) are lazy in Realm. Data is only read when objects and properties are accessed. This allows you to represent large sets of data in a performant way.

When performing queries you are returned a Results object. Results are simply a view of your data and are not mutable.

The most basic method for retrieving objects from a Realm is using the objects method on a Realm to get all objects of a given type:

letdogs=realm.objects('Dog');// retrieves all Dogs from the Realm

Filtering

You can get a filtered Results by calling the filtered method with a query string.

For example, the following would change our earlier example to retrieve all dogs with the color tan and names beginning with ‘B’:

At the moment only a subset of the NSPredicate syntax is supported in the query language. Basic comparison operators ==, !=, >, >=, <, and <= are supported for numeric properties. ==, BEGINSWITH, ENDSWITH, and CONTAINS are supported for string properties. String comparisons can be made case insensitive by appending [c] to the operator: ==[c], BEGINSWITH[c] etc. Filtering by properties on linked or child objects can by done by specifying a keypath in the query eg car.color == 'blue'.

Sorting

Results allows you to specify a sort criteria and order based on a single or multiple properties. For example, the following call sorts the returned cars from the example above numerically by miles:

Note that the order of Results is only guaranteed to stay consistent when the query is sorted. For performance reasons, insertion order is not guaranteed to be preserved.

Auto-Updating Results

Results instances are live, auto-updating views into the underlying data, which means results never have to be re-fetched. Modifying objects that affect the query will be reflected in the results immediately.

This applies to all Results instances, included those returned by the objects, filtered, and sorted methods.

This property of Results not only keeps Realm fast and efficient, it allows your code to be simpler and more reactive. For example, if your view relies on the results of a query, you can store the Results in a property and access it without having to make sure to refresh its data prior to each access.

You can subscribe to notifications to know when Realm data is updated, indicating when your app’s UI should be refreshed for example, without having to re-fetch your Results.

Limiting Results

Most other database technologies provide the ability to ‘paginate’ results from queries (such as the ‘LIMIT’ keyword in SQLite). This is often done out of necessity to avoid reading too much from disk, or pulling too many results into memory at once.

Since queries in Realm are lazy, performing this sort of paginating behavior isn’t necessary at all, as Realm will only load objects from the results of the query once they are explicitly accessed.

If for UI-related or other implementation reasons you require a specific subset of objects from a query, it’s as simple as taking the Results object, and reading out only the objects you need.

letcars=realm.objects('Car');// get first 5 Car objectsletfirstCars=cars.slice(0,5);

Realms

Opening Realms

Opening a Realm is simply performed by instantiating a new Realm object. Pass a configuration object to the constructor. We’ve seen this used already in examples with a configuration object that includes the schema key:

// Get the default Realm with support for our objectsletrealm=newRealm({schema:[Car,Person]});

For full details about the configuration object, see the API Reference for configuration. Some of the more common keys for the object, beyond schema, include:

sync: a sync object, to open a Realm synchronized with the Realm Object Server

The Default Realm

You may have noticed in all previous examples that the path argument has been omitted. In this case the default Realm path is used. You can access and change the default Realm path using the Realm.defaultPath global property.

Other Realms

It’s sometimes useful to have multiple Realms persisted at different locations. For example, you may want to bundle some data with your application in a Realm file, in addition to your main Realm. You can do this by specifying the path argument when initializing your realm. All paths are relative to the writable documents directory for your application:

// Open a realm at another pathletrealmAtAnotherPath=newRealm({path:'anotherRealm.realm',schema:[CarSchema]});

Schema Version

Another option available when opening a Realm is the schemaVersion property. When omitted, the schemaVersion property defaults to 0. You are required to specify the schemaVersion when initializing an existing Realm with a schema that contains objects that differ from their previous specification. If the schema was updated and the schemaVersion was not, an exception will be thrown.

constPersonSchema={name:'Person',properties:{name:'string'}};// schemaVersion defaults to 0letrealm=newRealm({schema:[PersonSchema]});constUpdatedPersonSchema={// The schema name is the same, so previous `Person` object// in the Realm will be updatedname:'Person',properties:{name:'string',dog:'Dog'// new property}};// this will throw because the schema has changed// and `schemaVersion` is not specifiedletrealm=newRealm({schema:[UpdatedPersonSchema]});// this will succeed and update the Realm to the new schemaletrealm=newRealm({schema:[UpdatedPersonSchema],schemaVersion:1});

If you wish to retrieve the current schema version of a Realm, you may do so with the Realm.schemaVersion method.

letcurrentVersion=Realm.schemaVersion(Realm.defaultPath);

Asynchronously Opening Realms

If opening a Realm might require a time-consuming operation, such as applying migrations or downloading the remote contents of a synchronized Realm, you should use the openAsync API to perform all work needed to get the Realm to a usable state on a background thread before dispatching to the given queue. You should also use openAsync with Realms that are set read-only.

For example:

Realm.openAsync({schema:[PersonSchema],schemaVersion:42,migration:function(oldRealm,newRealm){// perform migration (see "Migrations" in docs)}},(error,realm)=>{if(error){return;}// do things with the realm object returned by openAsync to the callbackconsole.log(realm);})

The openAsync command takes a configuration object as its first parameter and a callback as its second; the callback function receives a boolean error flag and the opened Realm.

Initial Downloads

In some cases, you might not want to open a Realm until it has all remote data available. In such a case, use openAsync. When used with a synchronized Realm, this will download all of the Realm’s contents before the callback is invoked.

varcarRealm;Realm.openAsync({schema:[CarSchema],sync:{user:user,url:'realm://object-server-url:9080/~/cars'}},(error,realm)=>{if(error){return;}// Realm is now downloaded and ready for usecarRealm=realm;});

Migrations

When working with a database your data model will most likely change over time. For example, suppose we have the following Person model:

We want to update the data model to require a name property, rather than separate first and last names. To do this, we simply change the schema to the following:

varPersonSchema={name:'Person',properties:{name:'string',age:'int'}}

At this point if you had saved any data with the previous model version there will be a mismatch between the new code and the old data Realm has stored on disk. When this occurs, an exception will be thrown when you try to open the existing Realm with the new schema unless you run a migration.

Performing a Migration

You define a migration and the associated schema version by updating the schemaVersion and defining an optional migration function. Your migration function provides any logic needed to convert data models from previous schemas to the new schema. When opening a Realm the migration function will be applied to update the Realm to the given schema version only if a migration is needed.

If no migration function is supplied then any new properties an automatically added and old properties are removed from the database when updating to the new schemaVersion. If you need to update old or populate new properties when upgrading your version you can do this in the migration function. For example, suppose we want to migrate the Person model declared earlier. You can populate the name property of the new schema using the old firstName and lastName properties:

varrealm=newRealm({schema:[PersonSchema],schemaVersion:1,migration:function(oldRealm,newRealm){// only apply this change if upgrading to schemaVersion 1if(oldRealm.schemaVersion<1){varoldObjects=oldRealm.objects('Person');varnewObjects=newRealm.objects('Person');// loop through all objects and set the name property in the new schemafor(vari=0;i<oldObjects.length;i++){newObjects[i].name=oldObjects[i].firstName+' '+oldObjects[i].lastName;}}}});varfullName=realm.objects('Person')[0].name;

Once the migration is successfully completed the Realm and all of its objects can be accessed as usual by your app.

Linear Migrations

With the migration pattern described above you can potentially run into issues when migrating over multiple versions. This could happen if a user skips an app update and a property has been changed multiple times in the versions being skipped. In this case you may need to edit old migration code to correctly update data from old schema to the latest schema.

It’s possible to avoid this issue by running multiple migrations sequentially, making sure that the database is upgraded to each previous version and that the associated migration code is run. When following this pattern old migration code should never have to be modified, although you will need to keep all old schema and migration blocks for future use. An example of what this would look like:

varschemas=[{schema:schema1,schemaVersion:1,migration:migrationFunction1},{schema:schema2,schemaVersion:2,migration:migrationFunction2},...]// the first schema to update to is the current schema version// since the first schema in our array is atvarnextSchemaIndex=Realm.schemaVersion(Realm.defaultPath);while(nextSchemaIndex<schemas.length){varmigratedRealm=newRealm(schemas[nextSchemaIndex++]);migratedRealm.close();}// open the Realm with the latest schemavarrealm=newRealm(schemas[schemas.length-1]);

Notifications

The Realm, Results and List objects provide addListener methods to register notification callbacks. Whenever the object is updated, the change notification callback will be called.

There are two kinds of notifications, “Realm Notifications” (simple callbacks notified when write transactions are committed) and “Collection Notifications” (more sophisticated callbacks which receive change metadata on insertions, deletions and updates).

In addition, the Professional Edition and Enterprise Edition provide event handling notifications. Read “The Realm Mobile Platform” for more information.

Realm Notifications

Realm instances send out notifications to other instances every time a write transaction is committed. To register for notifications:

Collection Notifications

Collection notifications contain information that describe what changes have occurred at a fine-grained level. This consists of the indices of objects that have been inserted, deleted, or modified since the last notification. Collection notifications are delivered asynchronously: first with the initial results, and then after any write transaction which modifies any of the objects in the collection, deletes objects from the collection, or adds new objects to the collection.

The notification callback function given to addListener receives two parameters when these changes occur. The first one is the collection that changed, and the second one is a changes object with information about the collection indices affected by deletions, insertions and modifications.

The former two, deletions and insertions, record the indices whenever objects start and stop being part of the collection. This takes into account when you add objects to the Realm or delete them from the Realm. For Results this also applies when you filter for specific values and the object was changed so that it is now matching the query or not matching anymore. For collections based on List, this applies when objects are added or removed from the relationship.

Your application is notified about modifications whenever a property of an object has changed, which was previously part of the collection and is still part of it. This happens as well when to-one and to-many relationships change, but doesn’t take changes on inverse relationships into account.

Sync

The Realm Mobile Platform (RMP) extends the Realm Mobile Database across the network, enabling automatic synchronization of data across devices. In order to do this a new set of types and classes are provided that support these synchronized Realms; these new classes are additive to the existing Realm Mobile Database.

Users

The central object in the Realm Object Server is the Realm User (Realm.Sync.User) associated with a synchronized Realm. A User can be authenticated to a shared Realm via a username/password scheme, or through a number of third-party authentication methods.

Creating and logging in a user requires two things:

A URL of a Realm Object Server to connect to.

Credentials for an authentication mechanism that describes the user as appropriate for that mechanism (i.e., username/password, access key, etc).

Authentication

Authentication is used to establish the identity of users and log them in. Refer to our authentication documentation for a list of authentication providers supported by the Realm Mobile Platform.

The credential information for a given user can be created in one of several ways:

Providing a valid username/password combination

Providing a token obtained from a supported third-party authentication service

The username and password authentication is entirely managed by the Realm Object Server, giving you full control over your application’s user management. For other authentication methods, your application is responsible for logging into the external service and obtaining the authentication token.

Note: the JavaScript SDK does not currently allow you to send additional data. If you need to send more than a single token, please encode the additional data as JSON and pass it through the accessToken parameter, and decode this string on the server side.

Logging Out

Logging out of a synced Realm is simple:

user.logout();

When a user is logged out, the synchronization will stop. A logged out user can no longer open a synced Realm.

Working with Users

The sync server URL may contain the tilde character (“~”) which will be transparently expanded to represent the user’s unique identifier. This scheme easily allows you to write your app to cater to its individual users. The location on disk for shared Realms is managed by the framework, but can be overridden if desired.

Realm.Sync.User.current can be used to obtain the currently logged in user. If no users have logged in or all have logged out, it will return undefined. If there are more than one logged in users, an error will be thrown.

letuser=Realm.Sync.User.current;

If there are likely to be multiple users logged in, you can get a collection of them by calling Realm.Sync.User.all. This will be empty if no users have logged in.

letusers=Realm.Sync.User.all;for(constkeyinusers){constuser=users[key];// do something with the user. })

Opening a Synchronized Realm

Once you have opened a Realm using a URL to a Realm Object Server and a User object, you can interact with it as you would any other Realm in JavaScript.

Sync Sessions

A synced Realm’s connection to the Realm Object Server is represented by a Session object. Session objects can be retrieved by calling realm.syncSession.

The state of the underlying session can be retrieved using the state property. This can be used to check whether the session is active, not connected to the server, or in an error state.

Access Control

The Realm Mobile Platform provides flexible access control mechanisms to restrict which users are allowed to sync against which Realm files. This can be used, for example, to create collaborative apps where multiple users write to the same Realm. It can also be used to share data in a publisher/subscriber scenario where a single writing user shares data with many users with read permissions.

There are three permissions that control the access level of a given Realm for a User:

mayRead indicates that the user is allowed to read from the Realm.

mayWrite indicates that the user is allowed to write to the Realm.

mayManage indicates that the user is allowed to change the permissions for the Realm.

Unless permissions are explicitly modified, only the owner (creator) of a Realm can access it. The only exception is admin users: They are always granted all permissions to all Realms on the server.

Write-only permissions (i.e., mayWrite set without mayRead) are not currently supported.

Please refer to the general Realm Object Server documentation on Access Control to learn more about the concept.

Management Realm

All access level management operations are performed by writing to the Management Realm. The Management Realm is just like a regular synchronized Realm, but that the Realm Object Server is specifically designed to react to by default. Permission modifying objects can be added to the Realm to apply those changes to the access control settings of a Realm file.

To obtain the Management Realm for a given User, call its user.openManagementRealm() method:

constmanagementRealm=user.openManagementRealm();

Modifying Permissions

Modifying the access control settings for a Realm file is done by adding permission object instances to the management Realm. Currently, there are two workflows supported:

PermissionChange

The PermissionChange object allows you to directly control the access control settings for a Realm. This is useful when you already know the Ids of the users you want to grant permissions to, or want to grant permissions to everyone.

To apply the permission changes for all Realms managed by the User, specify a realmURL value of *.

To apply the permission changes for all Users authorized with the Object Server, specify a userId value of *.

If you don’t supply values for mayRead, mayWrite, or mayManage, or you supply null, the read, write, or manage permissions will be left unchanged. This can be useful, for example, if you want to grant users read permissions, but don’t want to take away write permissions from people who already have it:

This way, all users in the list will be granted read permissions, but those who had write or manage access will not lose it.

PermissionOffer/PermissionResponse

The PermissionOffer and PermissionOfferResponse pair of classes allows you to design sharing scenarios where an inviter generates a token, which can then be consumed by one or more users:

managementRealm.write(()=>{letexpirationDate=newDate();expirationDate.setDate(expirationDate.getDate()+7);// Expires in a week.managementRealm.create('PermissionOffer',{id:generateUniqueId(),createdAt:newDate(),updatedAt:newDate(),userId:userId,realmUrl:realmUrl,mayRead:true,mayWrite:true,mayManage:false,expiresAt:expirationDate});});/* Wait for the offer to be processed */vartoken=permissionOffer.token;/* Send token to the other user */

Similarly to PermissionChange, there are arguments controlling the read, write, and manage access for the Realm at the supplied realmUrl. One additional argument you can provide is expiresAt which controls when the token will no longer be consumable. If you don’t pass a value or pass null, the offer will never expire. Note that users who have consumed the offer will not lose access after it expires.

Once another user has obtained the token, they can consume it:

constmanagementRealm=anotherUser.openManagementRealm();letofferResponse;managementRealm.write(()=>{offerResponse=managementRealm.create('PermissionOfferResponse',{id:generateUniqueId(),createdAt:newDate(),token:token});});/* Wait for the offer to be processed */constrealmUrl=offerResponse.realmUrl;// Now we can open the shared realm:varrealm=newRealm({sync:{user:anotherUser,url:realmUrl,},schema:[/* ... */]});

Note that permissions granted by consuming a PermissionOffer are additive, i.e. if a user already has write access and accepts a PermissionOffer granting read permissions, they will not lose their write access.

PermissionOffers can be revoked by deleting them from the Management Realm or setting expiresAt to a date in the past. This will prevent new users from accepting the offer, but will not revoke any permissions of users who had consumed it prior to that.

Once the Object Server has processed the operations encoded in the permission object, it will set that object’s statusCode and statusMessage properties.

React Native ListView

If you’d like to use List or Results instances as data for a ListView, it is highly recommended that you use the ListView and ListView.DataSource provided by the realm/react-native module:

import{ListView}from'realm/react-native';

The API is exactly the same as React.ListView, so you can refer to the ListView documentation for usage information.

Encryption

Please take note of the Export Compliance section of our LICENSE, as it places restrictions against the usage of Realm if you are located in countries with an export restriction or embargo from the United States.

Realm supports encrypting the database file on disk with AES-256+SHA2 by supplying a 64-byte encryption key when creating a Realm.

varkey=newInt8Array(64);// pupulate with a secure keyvarrealm=newRealm({schema:[CarObject],encryptionKey:key});// Use the Realm as normalvardogs=realm.objects('Car');

This makes it so that all of the data stored on disk is transparently encrypted and decrypted with AES-256 as needed, and verified with a SHA-2 HMAC. The same encryption key must be supplied every time you obtain a Realm instance.

There is a small performance hit (typically less than 10% slower) when using encrypted Realms.

Troubleshooting

Missing Realm Constructor

If your app crashes, telling you that the Realm constructor was not found, there are a few things you can try:

First of all, run react-native link realm

If that doesn’t help, and your problem is on Android, try:

Add the following in your MainApplication.java file: java import io.realm.react.RealmReactPackage;

If your problem is on iOS, try: 1. Close all simulators/device builds 2. Stop the package manager running in terminal (or better yet, just restart terminal) 3. Open the ios folder in your app root in finder 4. Go into the build folder (note: you won’t see this build folder in atom, so just right click ios and click open in finder) 5. Delete everything inside of the build folder (just move to trash and keep trash around in case you’re worried) 6. Run react-native run-ios to rebuild the whole thing

Crash Reporting

We encourage you to use a crash reporter in your application. Many Realm operations could potentially fail at runtime (like any other disk IO), so collecting crash reports from your application will help identify areas where either you (or us) can improve error handling and fix crashing bugs.

Most commercial crash reporters have the option of collecting logs. We strongly encourage you to enable this feature. Realm logs metadata information (but no user data) when throwing exceptions and in irrecoverable situations, and these messages can help debug when things go wrong.

Reporting Realm Issues

If you’ve found an issue with Realm, please either file an issue on GitHub or email us at help@realm.io with as much information as possible for us to understand and reproduce your issue.

The following information is very useful to us:

Goals.

Expected results.

Actual results.

Steps to reproduce.

Code sample that highlights the issue (full working projects that we can compile ourselves are ideal).