Docs Menu
Docs Home
/ /
Atlas Device SDK
/ /

Realm ファイルのバンドル - Swift SDK

項目一覧

  • Overview
  • バンドル用の Realm ファイルの作成
  • 本番アプリケーションでの Realm ファイルのバンドル
  • バンドルされた Realm ファイルから Realm を開く

注意

同期された Realm のバンドル

Swift SDK バージョン10.23.0 同期された Realm をバンドルする機能を導入しました。 バージョン10.23.0より前は、 バンドルできるのはローカル Realm のみです。

Realm は Realm ファイルのバンドルをサポートしています。 Realm ファイルをバンドルする場合、データベースとそのすべてのデータをアプリケーションのダウンロードに含めます。

これにより、ユーザーは初期データセットを使用して初めてアプリケーションを起動できます。 同期済み Realm の場合、バンドルにより、ユーザーが初めてアプリケーションを開くときに長時間かかる初期ダウンロードを回避できます。 代わりに、ユーザーは、バンドル ファイルの生成以降に発生した同期された変更のみをダウンロードする必要があります。

重要

同期された Realm のバンドル

バックエンド アプリケーションで Flexible Syncを使用している場合、バンドルされている Realm ファイルを初めて開くときにクライアントがリセットされる可能性があります。 これは、クライアント最大オフライン時間が有効になっている場合に発生する可能性があります(クライアントの最大オフライン時間はデフォルトで有効になっています)。 ユーザーが最初に同期する前に、バンドルされた Realm ファイルがクライアントの最大オフライン時間設定で指定された日数を超えて生成された場合、ユーザーはクライアントをリセットします。

クライアントリセットを実行するアプリケーションは、アプリケーション バックエンドから Realm の完全な状態をダウンロードします。 これにより、Realm ファイルをバンドルする利点が得られません。 クライアントのリセットを防ぎ、Realm ファイルのバンドルの利点を維持するには、次の手順に従います。

  • 同期された Realm をバンドルするアプリケーションでは、クライアントの最大オフライン時間を使用しないでください。

  • アプリケーションがクライアントの最大オフライン時間を使用する場合は、アプリケーションのダウンロードに最近同期された Realm ファイルが常に含まれていることを確認してください。 アプリケーション バージョンごとに新しい ファイルを生成し、クライアントの最大オフライン時間数を超えてどのバージョンも最新の状態に維持します。

Realm ファイルを作成してアプリケーションにバンドルするには、次の手順に従います。

  1. バンドルするデータを含むRealm ファイルを作成します

  2. 本番アプリケーションにRealm ファイルをバンドルします。

  3. 本番アプリケーションで、バンドルされた アセット ファイル から Realm を開きます。 同期された Realm の場合は、パーティションキーを指定する必要があります。

  1. アプリケーションのデータモデルを共有する一時的な Realm アプリを構築します。

  2. Realm を開き、バンドルするデータを追加します。 同期された Realm を使用する場合は、Realm が完全に同期するまで時間を待ちます。

  3. writeCopy(configuration:)メソッドを使用して、Realm を新しいファイルにコピーします。

Tip

アプリが async/awaitコンテキストで Realm にアクセスする場合は、スレッド関連のクラッシュを回避するためにコードを@MainActorでマークします。

try await createBundledRealm()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func createBundledRealm() async throws {
let app = App(id: YOUR_APP_SERVICES_APP_ID)
// Log in the user whose realm you want to copy for bundling
let seedUser = try await app.login(credentials: Credentials.anonymous)
// Create a configuration to open the seed user's realm
var config = seedUser.configuration(partitionValue: "Partition You Want to Bundle")
config.objectTypes = [Todo.self]
// Open the realm with the seed user's config
let realm = try await Realm(configuration: config, downloadBeforeOpen: .always)
print("Successfully opened realm: \(realm)")
// Verify there is a todo object in the realm whose
// owner's name is "Daenerys". When we open the bundled
// realm later, we should see the same result.
let todos = realm.objects(Todo.self)
let daenerysTodos = todos.where { $0.owner == "Daenerys" }
XCTAssertEqual(daenerysTodos.count, 1)
// Specify an output directory for the bundled realm
// We're using FileManager here for tested code examples,
// but this could be a static directory on your computer.
guard let outputDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
// Append a file name to complete the path
let bundleRealmFilePath = outputDir.appendingPathComponent("seed.realm")
// Update the config file path to the path where you want to save the bundled realm
config.fileURL = bundleRealmFilePath
// Check to see if there is already a realm at the bundled realm file path. If there
// is already a realm there, delete it.
if Realm.fileExists(for: config) {
try Realm.deleteFiles(for: config)
print("Successfully deleted existing realm at path: \(bundleRealmFilePath)")
} else {
print("No file currently exists at path")
}
// Write a copy of the realm at the URL we specified
try realm.writeCopy(configuration: config)
// Verify that we successfully made a copy of the realm
XCTAssert(FileManager.default.fileExists(atPath: bundleRealmFilePath.path))
print("Successfully made a copy of the realm at path: \(bundleRealmFilePath)")
// Verify that opening the realm at the new file URL works.
// Don't download changes, because this can mask a copy
// that does not contain the expected data.
let copiedRealm = try await Realm(configuration: config, downloadBeforeOpen: .never)
print("Successfully opened realm: \(realm)")
// Verify that the copied realm contains the data we expect
let copiedTodos = copiedRealm.objects(Todo.self)
let daenerysCopiedTodos = copiedTodos.where { $0.owner == "Daenerys" }
XCTAssertEqual(daenerysCopiedTodos.count, 1)
print("Copied realm opens and contains this many tasks: \(daenerysCopiedTodos.count)")
}

writeCopy(構成: )は、コピーする前に Realm を可能な限り最小のサイズに自動的に圧縮します。

注意

同期された Realm とローカル専用 Realm の違い

上記の例では、 SyncConfigurationを使用して同期された Realm を構成しています。 ローカル Realm のコピーを作成するには、代わりにRealmConfigurationを使用して Realm を構成します。

初期データを含む Realm のコピーが用意できたら、それを本番アプリケーションにバンドルします。 大まかに言えば、これには次のことが含まれます。

  1. 本番アプリとまったく同じデータモデルで新しいプロジェクトを作成します。 Realm を開き、バンドルするデータを追加します。 Realm ファイルはクロスプラットフォームであるため、macOS アプリでこれを実行できます。

  2. Realm ファイルの圧縮されたコピーを本番アプリの Xcode プロジェクト ナビゲータにドラッグします。

  3. GoBuild PhasesXcode でアプリターゲットの [{0 ] タブに します。Realm ファイルをCopy Bundle Resourcesビルドフェーズに追加します。

  4. この時点で、アプリはバンドルされている Realm ファイルにアクセスできるようになります。 Bundle.main.path(forResource: ofType) でパスを見つけます。

Realm.ConfigurationreadOnlyプロパティがtrueに設定されている場合は、バンドル パスで Realm を直接開くことができます。 バンドルされている Realm を変更する場合は、まず構成上のバンドルされた Realm の URL を使用して、 seedFilePathを設定して、バンドルされた ファイルをアプリのドキュメント フォルダーにコピーします。

Tip

移行サンプル アプリ を見る は、バンドルされたローカル Realm を使用する完全に動作するアプリの ためのものです。

本番アプリケーションに含まれる Realm のコピーが作成できたら、それを使用するためのコードを追加する必要があります。 バンドルされた ファイルからRealmを開くようにRealmを構成するときは、シードファイルパス メソッドを使用します。

Tip

アプリがasync/awaitコンテキストで Realm にアクセスする場合は、スレッド関連のクラッシュを回避するためにコードを@MainActorでマークします。

try await openBundledSyncedRealm()
// Opening a realm and accessing it must be done from the same thread.
// Marking this function as `@MainActor` avoids threading-related issues.
@MainActor
func openBundledSyncedRealm() async throws {
let app = App(id: YOUR_APP_SERVICES_APP_ID)
// Log in an app user who will use the bundled realm
let user = try await app.login(credentials: Credentials.anonymous)
// Create a configuration for the app user's realm
// This should use the same partition value as the bundled realm
var newUserConfig = user.configuration(partitionValue: "Partition You Want to Bundle")
newUserConfig.objectTypes = [Todo.self]
// Find the path of the seed.realm file in your project
let realmURL = Bundle.main.url(forResource: "seed", withExtension: ".realm")
print("The bundled realm URL is: \(realmURL)")
// When you use the `seedFilePath` parameter, this copies the
// realm at the specified path for use with the user's config
newUserConfig.seedFilePath = realmURL
// Open the synced realm, downloading any changes before opening it.
// This starts with the existing data in the bundled realm, but checks
// for any updates to the data before opening it in your application.
let realm = try await Realm(configuration: newUserConfig, downloadBeforeOpen: .always)
print("Successfully opened the bundled realm")
// Read and write to the bundled realm as normal
let todos = realm.objects(Todo.self)
// There should be one todo whose owner is Daenerys because that's
// what was in the bundled realm.
var daenerysTodos = todos.where { $0.owner == "Daenerys" }
XCTAssertEqual(daenerysTodos.count, 1)
print("The bundled realm has \(daenerysTodos.count) todos whose owner is Daenerys")
// Write as usual to the realm, and see the object count increment
let todo = Todo(value: ["name": "Banish Ser Jorah", "owner": "Daenerys", "status": "In Progress"])
try realm.write {
realm.add(todo)
}
print("Successfully added a todo to the realm")
daenerysTodos = todos.where { $0.owner == "Daenerys" }
XCTAssertEqual(daenerysTodos.count, 2)
}

注意

同期された Realm とローカル専用 Realm の違い

上記の例では、 SyncConfigurationを使用して同期された Realm を構成しています。 ローカル Realm のコピーを作成するには、代わりにRealm.Configurationを使用して Realm を構成します。

戻る

Realm の削除