Realm の設定とオープン - Swift SDK
項目一覧
Realm を開く際に、Realm ファイルの構成方法に関する追加の詳細を指定する Realm.Configurationを渡すことができます。 これには、次のようなものが含まれます。
ファイルURL またはメモリ内識別子を渡して、Realm をデバイスに保存する方法をカスタマイズします
Realm との同期を使用するには、ログイン ユーザーと同期の詳細を指定します
アプリの クラスのサブセットのみを使用する Realm を指定する
ファイル サイズを縮小するためにRealmを圧縮するかどうか、またいつ圧縮するか
暗号化のキーを渡してRealmを暗号化
スキーマ変更を行う際に、スキーマのバージョンまたは移行ブロックを指定する
Tip
以下も参照してください。
このページでは、データ を同期しない Realm ファイルを開く方法について説明します。 Device Sync を使用して他のデバイスとデータを同期する場合は、「同期された Realm の構成とオープン」を参照してください。
同期なしで Realm を開く
同期されていないローカル Realm は、いくつかの異なる構成オプションを使用して開くことができます。
構成なし - デフォルト構成
Realm のファイル URL の指定
ファイルをファイル システムに保存せず、メモリ内のみでRealmを開きます
同期された Realm をコピーして、同期なしで使用する
デフォルトの Realm または ファイル URL で Realm を開きます
+[RMRealm defaultRealm] を使用してデフォルトの邦土を開くことができます。
また、 RMRealmConfigurationオブジェクトを+[RMRealm RealmWithConfiguration:error:]に渡して、メモリ内の特定のファイル URL で Realm を開くことも、 Device Sync を使用して開くこともできます。
RMRealmConfiguration インスタンスを+[RMRealmConfiguration setDefaultConfiguration:] に渡すことで、デフォルトの Realm 構成を設定できます。
// 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];
Realm() 初期化を使用してRealmを開くことができます。 Realm.Configurationパラメータを省略すると、デフォルトの Realm が開きます。
新しい Realm.Configuration インスタンスをRealm.Configuration.defaultConfigurationに割り当てることで、デフォルトの Realm 構成を設定できます クラスのプロパティ
// 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)
インメモリ Realm のオープン
バージョン 10.46.0 での変更: メモリ内で同期されたデータベースを開くことをサポートします。
メモリ内でRealm全体を開くことができます。この場合、 .realm
ファイルやそれに関連する予備ファイルは作成されません。 代わりに、SDK は Realm が開いている間にオブジェクトをメモリに保存し、すべての インスタンスが閉じられるとすぐにそれらを破棄します。
このプロパティはfileURL
と組み合わせることはできないことに注意してください。 Swift SDK バージョン 10.45.3 以前では、このプロパティはsyncConfiguration
と組み合わせることはできません。
Realm 構成のinMemoryIdentifierプロパティを設定します。
// 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];
Realm 構成のinMemoryIdentifierプロパティを設定します。
// 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)
重要
特定の識別子を持つすべて のメモリ 内 RealmGo インスタンスが範囲を超えると、Realm はその Realm 内の すべてのデータ を削除し 。これを回避するには、アプリの有効期間中にメモリ内のRealmへの強力な参照を保持します。
Swift 同時実行機能で Realm を開く
Swift の async/await 構文を使用して、mainActor 分離の Realm を開くか、Realm を非同期に開くときにアクターを指定できます。
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) }
または、すべての Realm 操作を管理するカスタム Realm アクターを定義することもできます。
actor RealmActor { // An implicitly-unwrapped optional is used here to let us pass `self` to // `Realm(actor:)` within `init` var realm: Realm! init() async throws { realm = try await Realm(actor: self) } var count: Int { realm.objects(Todo.self).count } 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 ]) } } func getTodoOwner(forTodoNamed name: String) -> String { let todo = realm.objects(Todo.self).where { $0.name == name }.first! return todo.owner } 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) } 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) } } func deleteTodo(id: ObjectId) async throws { try await realm.asyncWrite { let todoToDelete = realm.object(ofType: Todo.self, forPrimaryKey: id) realm.delete(todoToDelete!) } } func close() { realm = nil } }
アクター分離された Realm は、ローカル アクターまたはグローバル アクターのいずれかで使用できます。
// A simple example of a custom global actor actor BackgroundActor: GlobalActor { static var shared = 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)") } func mainThreadFunction() async throws { try await backgroundThreadFunction() }
アクター分離された Realm の操作の詳細については、「 アクターでRealm を使用する - Swift SDK 」を参照してください。
Realm を閉じる
SwiftまたはObjective-Cでは、 邦土を手動で閉じる必要はありません。 邦土がスコープ外でメモリから削除された場合、 ARM は の場合、 邦土は閉じます。
Realm へのアクセス時のエラーの処理
Realm にアクセスするときにエラーを処理するには、 error
パラメータへのNSError
ポインターを指定します。
NSError *error = nil; RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration]; RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error]; if (!realm) { // Handle error return; } // Use realm
Realm にアクセスするときにエラーを処理するには、Swift に組み込まれているエラー処理メカニズムを使用します。
do { let realm = try Realm() // Use realm } catch let error as NSError { // Handle error }
Realm へのクラスのサブセットの提供
Tip
低メモリ制約での動作
watchOS アプリや iOS アプリ拡張機能などの一部のアプリケーションは、メモリのフットプリントに厳格な制約があります。 低メモリ環境用にデータモデルを最適化するには、クラスのサブセットを使用してRealmを開きます。
デフォルトでは、Swift SDK は 実行可能ファイル内のすべてのRMObjectおよびRRM埋め込みObjectからのクラスを Realm スキーマへの自動的に追加します。 どのオブジェクトを追加するかは、 RMRealmConfiguration オブジェクトの objectClasses プロパティを設定することで制御できます。
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 SDK は実行可能ファイル内のすべてのオブジェクトおよび埋め込みオブジェクト からのクラスを Realm スキーマに自動的に追加します。 どのオブジェクトを追加するかは、 Realm.Configuration オブジェクトの objectTypes プロパティを設定することで制御できます。
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)
Realm API を使用してプロパティを初期化
Realm API を使用して、値が初期化されるプロパティを定義できます。 例:
class SomeSwiftType { let persons = try! Realm().objects(Person.self) // ... }
この初期化コードが Realm 構成を設定する前に実行すると、予期しない動作が発生する可能性があります。 たとえば、 applicationDidFinishLaunching()
でデフォルトの Realm 構成の移行ブロックを設定しているが、 applicationDidFinishLaunching()
より前にSomeSwiftType
のインスタンスを作成している場合は、正しく構成される前に Realm にアクセスしている可能性があります。
このような問題を回避するには、次のいずれかを実行することを検討してください。
Realm API を使用してプロパティを早期に初期化するタイプのインスタンス化は、アプリが Realm 構成の設定を完了するまで延期されます。
Swift の
lazy
キーワードを使用してプロパティを定義します。 これにより、アプリが Realm 構成を設定するまで、lazy
プロパティにアクセスしようとしない限り、アプリケーションのライフサイクル中にいつでもこのようなタイプを安全にインスタンス化できます。ユーザー定義の構成を明示的に受け取る Realm API を使用してのみプロパティを初期化します。 使用している構成値が、Realm を開くために使用される前に、適切に設定されていることを確認できます。
デバイスがロックされているときに Realm を使用する
デフォルトでは、iOS 8 以降では、デバイスがロックされているたびにNSFileProtection
を使用してアプリファイルを暗号化します。 デバイスがロックされているときにアプリが Realm にアクセスしようとすると、次のエラーが表示される場合があります。
open() failed: Operation not permitted
これを処理するには、 Realm ファイルを含む フォルダのファイル保護をダウングレードします。 DNSFileProtectionCompleteUntilFirstUserAuthentication のような低い保護レベル デバイスがロックされている場合でもファイルにアクセスできるようにします。
Tip
iOS ファイルの暗号化を解除する場合は、代わりに Realmに組み込まれている暗号化を使用してデータを保護することを検討してください。
この例では、デフォルトの Realm の親ディレクトリに、より厳しい保護レベルを適用する方法を示しています。
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 ではいつでも予備ファイルを作成および削除できます。 ファイルのファイル保護をダウングレードする代わりに、親フォルダーに適用します。 こうすることで、作成時間に関係なく、関連するすべてのファイルにファイル保護が適用されます。