You are reading the documentation for an older version of Realm. You can view the latest documentation instead.

Realm React Nativeはアプリケーションのモデル層を効率的に安全で迅速な方法で記述することができます。下記の例をご覧ください:

// モデルクラスとスキーマを定義します
class Car {}
Car.schema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: 'int',
  }
};
class Person {}
Person.schema = {
  name: 'Person',
  properties: {
    name:    {type: 'string'},
    cars:    {type: 'list', objectType: 'Car'},
    picture: {type: 'data', optional: true}, // オプショナル(NULL可)のプロパティ
  }
};

// モデルクラスを与えてデフォルトRealmを取得します
let realm = new Realm({schema: [Car, Person]});

// Realmオブジェクトを作成してローカルDBに保存します
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 1000,
  });
  myCar.miles += 20; // 保存済みの値を更新することもできます
});

// 'miles > 1000'に該当するCarオブジェクトを検索します
let cars = realm.objects('Car').filtered('miles > 1000');

// 上記の条件に該当するCarオブジェクトは1件です
cars.size // => 1

// もう一つ別のCarオブジェクトを保存します
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Ford',
    model: 'Focus',
    miles: 2000,
  });

// 検索結果は自動的に最新の状態が映されます
cars.size // => 2

はじめに

Realm React Nativeはnpmを利用してインストールすることができます。ソースコードはGitHubにあります。

必要条件

  • React Nativeアプリケーションの開発環境が整っている必要があります。React Nativeの開発環境のセットアップについては公式サイトの説明をご覧ください。
  • 実行環境としてiOS、およびAndroidをサポートしています。
  • React Native 0.20.0以降をサポートしています。
  • React Nativeのパッケージマネージャであるrnpmの最新版がグローバルにインストールされている必要があります。

インストール

  • 新しくReact Nativeプロジェクトを作成します。

    react-native init <project-name>

  • 作成したプロジェクトのディレクトリに移動します(cd <project-name>)。さらにrealmを依存関係として追加します。

    npm install --save realm

  • 次に、rnpmを使ってプロジェクトとrealmネイティブモジュールをリンクします。

    sh rnpm link realm

ここまでで、Realmを使用する準備が整いました。下記の定義をindex.ios.jsまたはindex.android.jsファイルのclass <project-name>に記述して、Realmが正しくセットアップされているか試してみてください。

const Realm = require('realm');

class <project-name> extends Component {
 render() {
   let realm = new Realm({
     schema: [{name: 'Dog', properties: {name: 'string'}}]
   });

   realm.write(() => {
     realm.create('Dog', {name: 'Rex'});
   });

   return (
     <View style={styles.container}>
       <Text style={styles.welcome}>
         Count of Dogs in Realm: {realm.objects('Dog').length}
       </Text>
     </View>
   );
 }
}

デバイスまたはシミュレータを使って実行できます。

APIリファレンス

Realmで使用できるすべてのクラスとメソッドに関しては、APIリファレンスをご覧ください。

サンプルコード

サンプルコードを動かすにはまずRealm React NativeのプロジェクトをGitHubリポジトリからクローンします。

git clone https://github.com/realm/realm-js.git

サンプルプロジェクトはクローンしたリポジトリのexamples/ReactExampleフォルダに格納されています。初回のみ、サンプルを動かす前に、このディレクトリでnpm installを実行してください。

ヘルプ

  • 使い方に困ったときは、StackOverflowで#realmタグを付けて質問してください。私たちは毎日StackOverflowをチェックしています。
  • さらに複雑な問題に対する質問は、こちらの Slackチャットにて聞いてください。(質問は日本語で構いません)
  • 問題を発見した場合はGitHubのIssuesに報告してください。できる限り、ご使用のRealmのバージョン、エラーメッセージやログ、スアックトレースやRealmのデータファイル、問題を再現可能なプロジェクトなどを添えてください。
  • 機能のリクエストもGitHubのIssuesで教えてください。どのような機能が欲しいのか、また、どうしてその機能が必要なのかできるだけ具体的に教えてください。

もしクラッシュレポートツール(CrashlyticsやHockeyAppなど)を利用しているなら、ログコレクターを有効にしてください。Realmのログにはユーザーデータ以外のデバッグに有用なメタデータを含んでいます。それは私たちが問題を調査するときに非常に役に立ちます。

モデル

Realmのデータモデルは、スキーマの情報をRealmインスタンスの初期化時に渡すことによって定義されます。スキーマの情報とはモデルオブジェクトの名前、およびプロパティの名前や型などを示す一連の属性です。型は基本的な型に加えて、1対1の関連を示すobjectTypeや1対多の関連を示すリスト型が指定できます。またoptional(NULL可)やdefault(デフォルト値)についてもここで指定します。

var Realm = require('realm');

const CarSchema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: {type: 'int', default: 0},
  }
};
const PersonSchema = {
  name: 'Person',
  properties: {
    name:     'string',
    birthday: 'date',
    cars:     {type: 'list', objectType: 'Car'},
    picture:  {type: 'data', optional: true}, // オプショナル(NULL可)のプロパティ
  }
};

// CarとPersonのモデルクラスを指定してRealmを初期化します
let realm = new Realm({schema: [CarSchema, PersonSchema]});

既存のクラスを継承してモデルクラスを定義する場合は、スキーマをコンストラクタ内で定義して、コンストラクタをRealmの初期化時に渡します。

class Person {
  get ageSeconds() {
    return Math.floor((Date.now() - this.birthday.getTime()));
  }
  get age() {
    return ageSeconds() / 31557600000;
  }
}

Person.schema = PersonSchema;

// 注: `Person`クラスのコンストラクタをRealmに渡します
let realm = new Realm({schema: [CarSchema, Person]});

モデルクラスの定義ができていれば、オブジェクトをRealmに保存したり、検索することができます。

realm.write(() => {
  let car = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 750,
  });

  // モデルに定義したすべてのプロパティを読み書きできます
  console.log('Car type is ' + car.make + ' ' + car.model);
  car.miles = 1500;
});

対応しているデータ型

Realmでは、次に示すデータ型を基本的なデータ型としてサポートしています: boolintfloatdoublestringdataおよびdate

  • bool型のプロパティは、JavaScriptにおけるBoolean型にマッピングされます。
  • intfloatおよびdouble型のプロパティは、JavaScriptにおけるNumber型にマッピングされます。内部的にはintおよびdouble型は64ビットの値として保存されます。一方float型は32ビットの値として保存されます。
  • string型のプロパティはString型にマッピングされます。
  • data型のプロパティはArrayBuffer型にマッピングされます。
  • date型のプロパティはDate型にマッピングされます。

基本的なデータ型をプロパティに指定する場合は、省略記法が使えます。プロパティの属性を含むオブジェクトを渡す代わりに、型名を示す文字列を渡します。

const CarSchema = {
  name: 'Car',
  properties: {
    // 下記のtypeプロパティの定義はどちらも同じ意味です
    make:   {type: 'string'},
    model: 'string',
  }
}

オブジェクト型のプロパティ

1対1の関連として、オブジェクト型のプロパティを指定するには、型にスキーマに定義した別のオブジェクトの名前(name)を指定します。

const PersonSchema = {
  name: 'Person',
  properties: {
    // 下記のtypeプロパティの定義はどちらも同じ意味です
    car: {type: 'Car'},
    van: 'Car',
  }
};

オブジェクト型のプロパティを使用する場合は、Realmを初期化する際に、指定したすべてのオブジェクト型がスキーマに定義されている必要があります。

// PersonSchema内で'Car'型のプロパティとしてCarSchemaが使われているので、CarSchemaも渡す必要があります。
let realm = new Realm({schema: [CarSchema, PersonSchema]});

オブジェクト型のプロパティにアクセスする場合は、標準の文法を用いて、ネストしたプロパティとしてアクセスします。

realm.write(() => {
  var nameString = person.car.name;
  person.car.miles = 1100;

  // JSON記法を用いて新しくCar型のプロパティを作成して代入します。
  person.van = {make: 'Ford', model: 'Transit'};

  // 同じCar型のプロパティであるcarとvanに同じインスタンスを設定します。
  person.car = person.van;
});

リスト型のプロパティ

1対多の関連として、リスト型のプロパティを指定するには、list型としてスキーマに指定し、同時に格納する要素をobjectTypeに指定します。

const PersonSchema = {
  name: 'Person',
  properties: {
    cars: {type: 'list', objectType: 'Car'},
  }
}

リスト型のプロパティにアクセスするとListオブジェクトが返ります。Listオブジェクトは通常のJavaScriptの配列オブジェクトとほとんど同じメソッドを持っています。大きく異なる点は、Listオブジェクトに対する変更はすべて自動的に永続化されるという点です。さらに、Listオブジェクトは取得したオブジェクトが保持しています。そのため、Listオブジェクトをプログラマが自分で生成することはできません。別のオブジェクトのプロパティとしてアクセスし、取得します。

let carList = person.cars;

// CarオブジェクトをListに追加します
realm.write(() => {
  carList.push({make: 'Honda', model: 'Accord', miles: 100});
  carList.push({make: 'Toyota', model: 'Prius', miles: 200});
});

let secondCar = carList[1].model;  // 添字を使って各要素にアクセスします

オプショナル(NULL可)プロパティ

各プロパティはoptional属性を用いて、オプショナル(NULL可)、または非オプショナル(NULL不可)として定義できます。

const PersonSchema = {
  name: 'Person',
  properties: {
    name:     {type: 'string'},               // 必須(非オプショナル・NULL不可)プロパティ
    birthday: {type: 'date', optional: true}, // オプショナル(NULL可)プロパティ

    // オブジェクト型のプロパティは常にオプショナル(NULL可)です
    car:      {type: 'Car'},
  }
};

let realm = new Realm({schema: [PersonSchema, CarSchema]});

realm.write(() => {
  // オプショナル(NULL可)プロパティは生成時にはnullまたはundefinedを設定できます
  let charlie = realm.create('Person', {
    name: 'Charlie',
    birthday: new Date(1995, 11, 25),
    car: null,
  });

  // オプショナル(NULL可)プロパティは`null`、`undefined`、
  // または通常の値のいずれかを設定できます
  charlie.birthday = undefined;
  charlie.car = {make: 'Honda', model: 'Accord', miles: 10000};
});

上記に示す通り、オブジェクト型のプロパティは明示的に指定しなくても常にオプショナルとして扱われます。一方、List型のプロパティはオプショナルとして定義することはできず、nullをセットすることはできません。List型のプロパティを空にする際は、プロパティに空の配列をセットします。

デフォルト値

各プロパティはdefault属性を用いて、デフォルト値を定義できます。デフォルト値を設定したいプロパティは、オブジェクトの生成時にそのプロパティはundefinedのままにしておきます。

const CarSchema = {
  name: 'Car',
  properties: {
    make:  {type: 'string'},
    model: {type: 'string'},
    drive: {type: 'string', default: 'fwd'},
    miles: {type: 'int',    default: 0}
  }
};

realm.write(() => {
  // `miles`プロパティは何も指定していないのでデフォルト値の`0`が設定されます。
  // また`drive`プロパティはここで指定しているので、デフォルト値は使用されず指定した値で上書きされます。
  realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'});
});

インデックス付きプロパティ

プロパティの定義中でindexed属性をtrueに設定すると、そのプロパティにはインデックスが付加されます。 intstring、およびbool型のプロパティはインデックスに対応しています。

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:

var BookSchema = {
  name: 'Book',
  properties: {
    name: { type: 'string', indexed: true },
    price: 'float'
  }
};

プロパティをインデックスに登録することは同値性を比較するクエリの速度を大幅に向上します。その代わりにオブジェクトを作成する速度は少し遅くなります。

プライマリキー

string型およびint型のプロパティについてはprimaryKey属性を用いてプライマリキーとして指定できます。プラオマリキーが定義されていると、オブジェクトの検索と更新を効率的に行えることに加え、値が重複していないことを保証できます。プライマリキーが設定されたオブジェクトは、Realmに保存した後でプライマリキーの値を変更することはできなくなります。

const PersonSchema = {
  name: 'Person',
  primaryKey: 'id',
  properties: {
    id:   'int',    // プライマリキー
    name: 'string'
  }
};

プライマリキーとして指定したプロパティは自動的にインデックスが付加されます。

書き込み

Realmへのオブジェクトの追加、変更、削除は、トランザクションの内部で行う必要があります。

トランザクションのオーバーヘッドは大きいのでコード中のトランザクションが最小になるように設計してください。

オブジェクトの生成

これまでに説明したように、オブジェクトの生成にはcreateメソッドを使用します。

let realm = new Realm({schema: [CarSchema]);

realm.write(() => {
  realm.create('Car', {make: 'Honda', model: 'Accord', drive: 'awd'});
});

ネストしたオブジェクト

オブジェクト型のプロパティを持つオブジェクトは、各オブジェクトのプロパティの値をJSONを用いて再帰的に子のプロパティも含めて一度に生成できます。

let realm = new Realm({schema: [PersonSchema, CarSchema]);

realm.write(() => {
  realm.create('Person', {
    name: 'Joe',
    // ネストしたオブジェクトを1度に再帰的に生成できます
    car: {make: 'Honda', model: 'Accord', drive: 'awd'},
  });
});

オブジェクトの更新

プロパティへの代入

オブジェクトを更新するには、トランザクションの中でプロパティに値を設定します。

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

プライマリキーを使ってオブジェクトを作成・更新する

モデルにプライマリキーを指定しているなら、オブジェクトがすでに存在する場合は更新、存在しない場合は新しく追加というように、追加または更新を一度に行うことができます。この機能を利用するにはcreateメソッドの3つ目の引数にtrueを渡します。

realm.write(() => {
  // Bookオブジェクトを生成して保存します
  realm.create('Book', {primaryId: 1, title: 'Recipes', price: 35});

  // 上で保存したBookオブジェクトのPriceプロパティをプライマリキーを指定して更新します
  realm.create('Book', {primaryId: 1, price: 55}, true);
});

上記の例では、最初に保存されたBookオブジェクトはプライマリキーとしてprimaryIdプロパティを持ち、プライマリキーは1です。次の行で同じプライマリキー1を持つオブジェクトを渡し、3つ目の引数をtrueに指定します。そのため、新しくオブジェクトが作成されるのではなく、既存のオブジェクトのpriceプロパティが更新されます。nameプロパティは渡しているオブジェクトに含まれていないので、更新されず元の値が維持されます。

オブジェクトの削除

オブジェクトを削除するにはトランザクションの中でdeleteメソッドを使用します。

realm.write(() => {
  // Bookオブジェクトを作成し、保存します
  let book = realm.create('Book', {primaryId: 1, title: 'Recipes', price: 35});

  // Bookオブジェクトを削除します
  realm.delete(book);

  // `Results`、`List`、またはJavaScriptの`Array`を渡すと
  // 1度に複数のオブジェクトを削除できます
  let allBooks = realm.objects('Book');
  realm.delete(allBooks); // すべてのBookオブジェクトを削除します
});

クエリ

Realmのクエリは、どれか1つのオブジェクト型を指定して保存されているオブジェクトをRealmから取得します。検索条件を指定して結果をフィルタしたり、並べ替えることもできます。すべてのクエリと検索結果のプロパティアクセスは自動的に遅延されます。実際のデータはオブジェクトとプロパティにアクセスしたときにのみ取得されます。このことにより、大量のデータでも効率よく扱うことができます。

クエリを実行するとResultsオブジェクトが返ります。Resultsは検索結果を表します。Resultsオブジェクトの内容を変更することはできません。

オブジェクトを検索するもっとも基本的なメソッドは、Realmobjectsメソッドです。引数で与えられた型のオブジェクトをすべて取得します。

let dogs = realm.objects('Dog'); // Realmに保存されているすべてのDogオブジェクトを取得します

検索条件を指定する

filteredメソッドにクエリ文字列で検索条件を渡すことで、Resultsオブジェクトに含まれるオブジェクトをフィルタすることができます。

下記の例では、先のDogオブジェクトをすべて取得する例に少し手を加えて、colorプロパティが”tan”かつnameが”B”から始まるオブジェクトを取得します。

let dogs = realm.objects('Dog');
let tanDogs = dogs.filtered('color = "tan" AND name BEGINSWITH "B"');

現在はNSPredicateの文法のうちの次に示す一部分のみをサポートしています。基本的な比較演算子である==!=>>=<<=は数値型のプロパティに対して使用できます。==BEGINSWITH、ENDSWITHCONTAINSは文字列に対して使用できます。文字列の比較では、==[c]BEGINSWITH[c]などのように、演算子に[c]を付加することによって大文字小文字を区別しない比較を行うことができます。関連のプロパティに対して検索条件を使用する場合は、クエリ中でcar.color == 'blue'`のようにキーパスを用いて指定します。

並べ替え

1つまたは複数のプロパティを指定してResultsを並べ替えることができます。下記の例では、milesプロパティの昇順で並べ替えます。

let hondas = realm.objects('Car').filtered('make = "Honda"');

// ホンダ製(make = "Honda")かつ、走行距離(miles)の昇順
let sortedHondas = hondas.sorted('miles');

クエリの実行結果(Results)の順序はソートしなければ保証されません。パフォーマンス上の都合により、オブジェクトの挿入順は保持されません。

検索結果(Results)の自動更新(ライブアップデート)

Resultsは常に最新の状態に自動的に更新されます。このため、同じ検索条件なら繰り返し検索を実行して、結果を取得し直す必要はありません。Resultsは常に現在の最新の状態を反映します。

let hondas = realm.objects('Car').filtered('make = "Honda"');
// hondas.length == 0

realm.write(() => {
  realm.create('Car', {make: 'Honda', model: 'RSX'});
});
// hondas.length == 1

この仕組みはすべてのResultsインスタンスに(検索条件や、並べ替えの有無にかかわらず)適用されます。

Resultsが持つこの性質によって、Realmは効率的で高速な処理を実現しています。さらにアプリケーションのコードをシンプルかつリアクティブにすることを可能にします。例えば、クエリの検索結果を表示するビューに対しては、Resultsを保持して直接データの表示に使うことで、アクセスするたびに再検索することなく、常に最新のデータを表示することができます。

合わせてRealmの変更通知イベントを利用すると、データが更新され、アプリケーションのUIをアップデートするタイミングがわかります。その場合も、Resultsを取得し直す必要はありません。

取得データの数を制限

Realm以外のほとんどのデータベースには検索結果を「ページネーション(ページング)」する仕組みが備わっています(例えばSQLiteの’LIMIT’句によるものなどです)。この仕組みはディスクの過剰な読み込み、あるいは一度に大量のデータをメモリに読み込むことを避けるために使われます。

Realmのクエリは遅延実行されるので、このような「ページネーション」の仕組みはまったく必要ありません。なぜなら、Realmはクエリの実行結果の要素に対して、実際にアクセスしたときだけオブジェクトを読み込むからです。

UIや実装の都合により、クエリの実行結果の一部分だけが必要だったとします。そのときは、単にResultsオブジェクトを用いて、必要な要素にだけアクセスすれば良いのです。

let cars = realm.objects('Car');

// データを5件に制限したい場合は、
// 単に最初から5番目までのオブジェクトにアクセスします
let firstCars = cars.slice(0, 5);

Realmについて

複数のRealmを使い分ける

複数のRealmファイルを別の場所に保存して使い分けることができると便利です。例えば、事前に用意した組み込み済みデータを、メインのデータファイルとは別に読み込み専用のRealmとして利用するなどです。

Realmオブジェクトの初期化時にpathを指定することで、Realmファイルの保存場所を指定できます。pathの指定はアプリケーションのドキュメントディレクトリからの相対パスになります。

// Realmをデフォルト値とは別の保存先を指定して取得します
let realmAtAnotherPath = new Realm({
  path: 'anotherRealm.realm',
  schema: [CarSchema]
});

デフォルトRealmの保存先

このドキュメントにおけるこれまでのコード例では、path引数を指定していなかったことにお気づきでしょう。path引数を指定しない場合は、デフォルトの保存先が使われます。デフォルトの保存先を知る、または変更するにはグローバルプロパティに定義されているRealm.defaultPathを使用します。

スキーマバージョン

Realmの初期化時に指定できる最後の1つのプロパティはschemaVersionです。指定しなかった場合は、デフォルトの値として0が使われます。既存のデータからスキーマを変更した場合は、必ずschemaVersionを初期化時に指定しなければなりません。もしスキーマが変更されているにもかかわらず、schemaVersionを指定しなかった場合は例外が発生します。

const PersonSchema = {
  name: 'Person',
  properties: {
    name: 'string'
  }
};

// schemaVersionのデフォルトは0です
let realm = new Realm({schema: [PersonSchema]});

const UpdatedPersonSchema = {
  // スキーマの`name`プロパティが同じなので`Person`オブジェクトのスキーマが
  // 更新されたことになります
  name: 'Person',
  properties: {
    name: 'string',
    dog:  'Dog'     // 新しいプロパティを追加
  }
};

// 下記の記述はスキーマが更新されているにもかかわらず、
// スキーマバージョンを指定していないので例外が発生します。
let realm = new Realm({schema: [UpdatedPersonSchema]});

// 下記の記述ではスキーマの更新が成功し、新しいスキーマのRealmを取得します
let realm = new Realm({schema: [UpdatedPersonSchema], schemaVersion: 1});

Realmを開く前に、スキーマバージョンがいくつであるかを知るには、下記のようにRealm.schemaVersionメソッドを使用します。

let currentVersion = Realm.schemaVersion(Realm.defaultPath);

マイグレーション

データベースを使ってる場合、時間が経つにつれ、データモデルは変更されていくものです。例えば、以下のPersonモデルについて考えてみてください。

var PersonSchema = {
  name: 'Person',
  properties: {
    firstName: 'string',
    lastName: 'string',
    age: 'int'
  }
}

ここで、firstNamelastNameを一つにして、nameプロパティが必要になったとします。 そこで以下のような単純な変更をインターフェースに加えることにします。

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

ここでのポイントは、もし以前に前のデータモデルでのデータが保存されている場合、新しく定義し直したデータモデルとディスクに保存されている古いデータモデルとの間に不整合が生じてしまいます。 マイグレーションを実行せずに新しいスキーマを用いてRealmを使おうとすると、例外が発生します。

マイグレーションを実行する

スキーマバージョンとマイグレーション処理(migration function)(データを移行しなくてよいなら不要です)を更新してマイグレーション処理を定義します。 マイグレーション処理では古いデータ構造から新しいデータ構造に変換するための処理を記述します。 マイグレーション処理を記述すると、より新しいスキーマバージョンを指定してRealmを開こうとした際に適用されます。

schemaVersionだけを更新して、マイグレーション処理を記述しなかった場合は、オートマイグレーションによりデータベースに自動的に新しいプロパティが追加され、古いプロパティは自動的に削除されます。 スキーマを更新する際に、古いプロパティを更新したり、新しいプロパティにデータを移行する必要がある場合は、マイグレーション処理を書く必要があります。

たとえば、上記のPersonクラスのマイグレーションについて考えてみましょう。 新しく追加したnameプロパティには、古いfirstNamelastNameプロパティを結合した値を設定するとします。w

var realm = new Realm({
  schema: [PersonSchema],
  schemaVersion: 1,
  migration: function(oldRealm, newRealm) {
    // スキーマバージョンを1に更新する際に1度だけ実行されます
    if (oldRealm.schemaVersion < 1) {
      var oldObjects = oldRealm.objects('Person');
      var newObjects = newRealm.objects('Person');

      // 保存されているすべてのオブジェクトをループして新しいnameプロパティに値を設定します
      for (var i = 0; i < oldObjects.length; i++) {
        newObjects[i].name = oldObjecs[i].firstName + ' ' + oldObjects[i].lastName;
      }
    }
  }
});

var fullName = realm.objects('Person')[0].name;

一度マイグレーション処理が適用されると、その後は通常どおりにRealmとRealmオブジェクトが使用できます。

複数世代のマイグレーション

上記で示したマイグレーションのパターンでは、複数世代にわたるマイグレーションを実行した際に問題が起こることがあります。それはユーザーがプロパティのマイグレーションが必要なアプリのアップデートをスキップした場合に起こります。その場合、古いマイグレーションのコードを修正する必要に迫られるかもしれません。

この問題は、すべてのマイグレーションを古いものから順番に実行していくことで避けることができます。そうすることで、確実にすべてのマイグレーションが実行されて最新のデータ構造にアップデートされます。下記に示すパターンに従うことで、1度書いたマイグレーションのコードは2度と触る必要はありません。ただ、古いスキーマとマイグレーションのコードを将来にわたってもずっと保持し続ける必要があります。

下記の例を参考にしてください。

var schemas = [
  { 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 at
var nextSchemaIndex = Realm.schemaVersion(Realm.defaultPath);
while (nextSchemaIndex < schemas.length) {
  var migratedRealm = new Realm(schemas[nextSchemaIndex++]);
  migratedRealm.close();
}

// open the Realm with the latest schema
var realm = new Realm(schemas[schemas.length-1]);

変更通知イベント

トランザクションが完了した際には変更通知イベントが送られます。変更通知イベントを受けるためにはリスナーを登録します。

// Realmの変更通知イベントを監視します。
realm.addListener('change', () => {
  // このタイミングでUIを更新します
  ...
});

// 変更通知イベントの監視を解除します
realm.removeAllListeners();

React Native ListView

ListResultsのインスタンスをListViewのデータソースとして利用する場合は、realm/react-nativeモジュールにて提供されているListViewListView.DataSourceを利用することを強く推奨します。

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

realm/react-nativeモジュールが提供するListViewのAPIは完全にReact.ListViewと同じです。使い方はReact.ListViewのドキュメントをご覧ください。

暗号化

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では64バイトの暗号化キーを用いてAES-256とSHA-2暗号化方式でデータベースファイルを暗号化する機能を提供しています。

var key = new Int8Array(64);  // pupulate with a secure key
var realm = new Realm({schema: [CarObject], encryptionKey: key});

// Use the Realm as normal
var dogs = realm.objects('Car');

この機能を使用すると、ディスクに保存されるデータが透過的にAES-256で必要に応じて暗号/複合化され、SHA-2 HMACによって検証されます。

暗号化したRealmファイルのインスタンスを作成するには同じ暗号化キーが必要になります。

暗号化したRealmを使う場合、わずかにパフォーマンスが下がり(10%未満)ます。

トラブルシューティング

クラッシュレポート

私たちは開発者の方にクラッシュレポーターを使用していただくことを推奨しています。Realmの操作のうちの多くは(ディスクI/Oを伴う操作などと同様に)実行時に失敗する可能性があります。そのため、クラッシュレポートを収集することは、何が原因で問題が発生したのかを特定し、エラー処理の改善や不具合の修正に有効です。

多くの商用のクラッシュレポーターはログを収集するオプションを提供しています。この機能を有効にすることを強く推奨します。Realm例外が発生した時や、致命的な状態に陥った際にはメタデータの情報をログに出力しており(そこにユーザーデータは一切含まれていません)、それらのログは我々が問題を調査する際に役に立ちます。

Realmの問題や不具合を報告するには

Realmについて問題を発見した際は、GitHubで問題を報告するか、help@realm.ioにEメール、またはSlackで報告してください。その際には、こちらで問題を再現できるように、できるだけ多くの情報をあわせて教えてください。

下記に示す情報は問題を解決するために非常に役に立ちます。

  1. あなたが実際にやりたいこと・目的。
  2. 期待している結果。
  3. 実際に発生した結果。
  4. 問題の再現方法。
  5. 問題を再現、または理解できるサンプルコード (そのままビルドして実行できるプロジェクトだと理想的です)
  6. Realmのバージョン
  7. クラッシュログやスタックトレース。上述のクラッシュレポートの項目も参考にしてください。