CRUD - 作成 - Swift SDK
項目一覧
新しいオブジェクトの作成
このページの例について
このページの例では、次のモデルを使用します。
// DogToy.h @interface DogToy : RLMObject @property NSString *name; @end // Dog.h @interface Dog : RLMObject @property NSString *name; @property int age; @property NSString *color; // To-one relationship @property DogToy *favoriteToy; @end // Enable Dog for use in RLMArray RLM_COLLECTION_TYPE(Dog) // Person.h // A person has a primary key ID, a collection of dogs, and can be a member of multiple clubs. @interface Person : RLMObject @property int _id; @property NSString *name; // To-many relationship - a person can have many dogs @property RLMArray<Dog *><Dog> *dogs; // Inverse relationship - a person can be a member of many clubs @property (readonly) RLMLinkingObjects *clubs; @end RLM_COLLECTION_TYPE(Person) // DogClub.h @interface DogClub : RLMObject @property NSString *name; @property RLMArray<Person *><Person> *members; @end // Dog.m @implementation Dog @end // DogToy.m @implementation DogToy @end // Person.m @implementation Person // Define the primary key for the class + (NSString *)primaryKey { return @"_id"; } // Define the inverse relationship to dog clubs + (NSDictionary *)linkingObjectsProperties { return @{ @"clubs": [RLMPropertyDescriptor descriptorWithClass:DogClub.class propertyName:@"members"], }; } @end // DogClub.m @implementation DogClub @end
class DogToy: Object { var name = "" } class Dog: Object { var name = "" var age = 0 var color = "" var currentCity = "" var citiesVisited: MutableSet<String> var companion: AnyRealmValue // To-one relationship var favoriteToy: DogToy? // Map of city name -> favorite park in that city var favoriteParksByCity: Map<String, String> } class Person: Object { true) var id = 0 (primaryKey: var name = "" // To-many relationship - a person can have many dogs var dogs: List<Dog> // Embed a single object. // Embedded object properties must be marked optional. var address: Address? convenience init(name: String, address: Address) { self.init() self.name = name self.address = address } } class Address: EmbeddedObject { var street: String? var city: String? var country: String? var postalCode: String? }
オブジェクトの作成
Realm にオブジェクトを追加するには、他のオブジェクトと同様にそれをインスタンス化し、書込みトランザクション内で -[RMRealmObjectadd:]に渡します。
// Get the default realm. // You only need to do this once per thread. RLMRealm *realm = [RLMRealm defaultRealm]; // Instantiate the class. Dog *dog = [[Dog alloc] init]; dog.name = @"Max"; dog.age = 5; // Open a thread-safe transaction. [realm transactionWithBlock:^() { // Add the instance to the realm. [realm addObject:dog]; }];
Realm にオブジェクトを追加するには、他のオブジェクトと同様にそのオブジェクトをインスタンス化し、書込みトランザクション (write transaction) 内でRealm.add(_:update:)に渡します。
// Instantiate the class and set its values. let dog = Dog() dog.name = "Rex" dog.age = 10 // Get the default realm. You only need to do this once per thread. let realm = try! Realm() // Open a thread-safe transaction. try! realm.write { // Add the instance to the realm. realm.add(dog) }
値のあるオブジェクトを初期化
初期化値を Object.init(value:) に渡すことで、オブジェクトを初期化できます。初期化値は キーと値のコーディング が可能です 準拠オブジェクト、辞書、または各 管理プロパティの 1 つの要素を含む配列。
注意
配列を初期化値として使用する場合は、すべてのプロパティをモデルに定義されているのと同じ順序で含める必要があります。
// (1) Create a Dog object from a dictionary Dog *myDog = [[Dog alloc] initWithValue:@{@"name" : @"Pluto", @"age" : @3}]; // (2) Create a Dog object from an array Dog *myOtherDog = [[Dog alloc] initWithValue:@[@"Pluto", @3]]; RLMRealm *realm = [RLMRealm defaultRealm]; // Add to the realm with transaction [realm transactionWithBlock:^() { [realm addObject:myDog]; [realm addObject:myOtherDog]; }];
// (1) Create a Dog object from a dictionary let myDog = Dog(value: ["name": "Pluto", "age": 3]) // (2) Create a Dog object from an array let myOtherDog = Dog(value: ["Fido", 5]) let realm = try! Realm() // Add to the realm inside a transaction try! realm.write { realm.add([myDog, myOtherDog]) }
初期化値をネストすることで、関連オブジェクトや埋め込みオブジェクトも初期化できます。
// Instead of using pre-existing dogs... Person *aPerson = [[Person alloc] initWithValue:@[@123, @"Jane", @[aDog, anotherDog]]]; // ...we can create them inline Person *anotherPerson = [[Person alloc] initWithValue:@[@123, @"Jane", @[@[@"Buster", @5], @[@"Buddy", @6]]]];
// Instead of using pre-existing dogs... let aPerson = Person(value: [123, "Jane", [aDog, anotherDog]]) // ...we can create them inline let anotherPerson = Person(value: [123, "Jane", [["Buster", 5], ["Buddy", 6]]])
一部のプロパティ型は書込みトランザクションでのみ可変
一部のプロパティ型は、書込みトランザクションでのみ可変です。 たとえば、 MutableSetプロパティを使用してオブジェクトをインスタンス化できますが、そのプロパティの値は書込みトランザクション内でのみ設定できます。 書込みトランザクション内で初期化しない限り、そのプロパティの値でオブジェクトを初期化することはできません。
JSON によるオブジェクトの作成
Realm は JSON を直接サポートしていませんが、 JSONSerialization.jsonObject(with:options:) を 使用できます。 JSON を Realm.create(_:value:update:) に渡すことができる値に変換します。
// Specify a dog toy in JSON NSData *data = [@"{\"name\": \"Tennis ball\"}" dataUsingEncoding: NSUTF8StringEncoding]; RLMRealm *realm = [RLMRealm defaultRealm]; // Insert from NSData containing JSON [realm transactionWithBlock:^{ id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL]; [DogToy createInRealm:realm withValue:json]; }];
// Specify a dog toy in JSON let data = "{\"name\": \"Tennis ball\"}".data(using: .utf8)! let realm = try! Realm() // Insert from data containing JSON try! realm.write { let json = try! JSONSerialization.jsonObject(with: data, options: []) realm.create(DogToy.self, value: json) }
JSON 内のネストされたオブジェクトまたは配列は、 1と多の関係にマップされます。
JSON プロパティの名前とタイプは、宛先オブジェクト スキーマと完全に一致する必要があります。 例:
float
プロパティは、浮動小数点数のNSNumbers
で初期化する必要があります。Date
およびData
プロパティは、string から推論することはできません。 Realm.create(_:value:update:) に渡す前に、適切なタイプに変換します。必須 プロパティは、JSON に
null
または欠落していることはできません。
Realm は、オブジェクト スキーマに定義されていない JSON 内のプロパティを無視します。
Tip
JSON schema が Realm オブジェクトと完全に一致しない場合は、JSON を変換するためにサードパーティのフレームワークを使用することを検討してください。 Realm で動作する多くのモデル マッピング フレームワークがあります。 Realm-swift リポジトリの 部分的なリスト を参照してください。
埋め込みオブジェクトの作成
埋め込みオブジェクトを作成するには、埋め込みオブジェクトの インスタンスを親オブジェクトの プロパティに割り当てます。
RLMRealm *realm = [RLMRealm defaultRealm]; [realm transactionWithBlock:^{ Address *address = [[Address alloc] init]; address.street = @"123 Fake St."; address.city = @"Springfield"; address.country = @"USA"; address.postalCode = @"90710"; Contact *contact = [Contact contactWithName:@"Nick Riviera"]; // Assign the embedded object property contact.address = address; [realm addObject:contact]; NSLog(@"Added contact: %@", contact); }];
// Open the default realm let realm = try! Realm() try! realm.write { let address = Address() address.street = "123 Fake St" address.city = "Springfield" address.country = "USA" address.postalCode = "90710" let contact = Person(name: "Nick Riviera", address: address) realm.add(contact) }
マップ プロパティを持つオブジェクトの作成
マップ プロパティを持つオブジェクトを作成する場合、いくつかの方法でキーの値を設定できます。
オブジェクトにキーと値を設定し、そのオブジェクトを Realm に追加する
書込みトランザクション内でオブジェクトのキーと値を直接設定
キー値コーディングを使用して、書込みトランザクション内でキーと値を設定または更新
let realm = try! Realm() // Record a dog's name and current city let dog = Dog() dog.name = "Wolfie" dog.currentCity = "New York" // Set map values dog.favoriteParksByCity["New York"] = "Domino Park" // Store the data in a realm try! realm.write { realm.add(dog) // You can also set map values inside a write transaction dog.favoriteParksByCity["Chicago"] = "Wiggly Field" dog.favoriteParksByCity.setValue("Bush Park", forKey: "Ottawa") }
Realm では、マップキーに.
または$
文字を使用できません。 パーセント エンコーディングとデコーディング を使用して、これらの許可されていない文字の 1 つを含むマップキーを保存できます。
// Percent encode . or $ characters to use them in map keys let mapKey = "New York.Brooklyn" let encodedMapKey = "New York%2EBrooklyn"
MutableSet プロパティを持つオブジェクトの作成
Realm オブジェクトと同様にMutableSetプロパティを含むオブジェクトを作成できますが、MutableSet をミューテーションできるのは書込みトランザクション内のみです。 つまり、書込みトランザクション内で可変セットプロパティの値を設定できるということを意味します。
let realm = try! Realm() // Record a dog's name and current city let dog = Dog() dog.name = "Maui" dog.currentCity = "New York" // Store the data in a realm. Add the dog's current city // to the citiesVisited MutableSet try! realm.write { realm.add(dog) // You can only mutate the MutableSet in a write transaction. // This means you can't set values at initialization, but must do it during a write. dog.citiesVisited.insert(dog.currentCity) } // You can also add multiple items to the set. try! realm.write { dog.citiesVisited.insert(objectsIn: ["Boston", "Chicago"]) } print("\(dog.name) has visited: \(dog.citiesVisited)")
任意の RealmValue プロパティを持つオブジェクトの作成
AnyRealmValue プロパティを持つオブジェクトを作成する場合は、 プロパティに保存する値のタイプを指定する必要があります。 Realm Swift SDK は、AnyRealmValue が保存できるすべてのタイプを反復処理するAnyRealmValue 列挙型を提供します。
後で任意の RealmValue を読み取る際には、値を操作する前に 型を確認する必要があります。
// Create a Dog object and then set its properties let myDog = Dog() myDog.name = "Rex" // This dog has no companion. // You can set the field's type to "none", which represents `nil` myDog.companion = .none // Create another Dog whose companion is a cat. // We don't have a Cat object, so we'll use a string to describe the companion. let theirDog = Dog() theirDog.name = "Wolfie" theirDog.companion = .string("Fluffy the Cat") // Another dog might have a dog as a companion. // We do have an object that can represent that, so we can specify the // type is a Dog object, and even set the object's value. let anotherDog = Dog() anotherDog.name = "Fido" // Note: this sets Spot as a companion of Fido, but does not set // Fido as a companion of Spot. Spot has no companion in this instance. anotherDog.companion = .object(Dog(value: ["name": "Spot"])) // Add the dogs to the realm let realm = try! Realm() try! realm.write { realm.add([myDog, theirDog, anotherDog]) } // After adding these dogs to the realm, we now have 4 dog objects. let dogs = realm.objects(Dog.self) XCTAssertEqual(dogs.count, 4)
オブジェクトの非同期作成
Swift の同時実行機能を使用して、アクター分離された Realm に非同期に書込み (write) ができます。
RealmActor
Use Realm with Atlas で実行されている例 ] ページで定義されている例のこの関数は、アクター分離された Realm に書き込む方法を示しています。
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 ]) } }
そして、Swift の非同期構文を使用してこの書き込みを実行できます。
func createObject() async throws { // Because this function is not isolated to this actor, // you must await operations completed on the actor try await actor.createTodo(name: "Take the ring to Mount Doom", owner: "Frodo", status: "In Progress") let taskCount = await actor.count print("The actor currently has \(taskCount) tasks") } let actor = try await RealmActor() try await createObject()
この操作は、呼び出し元のスレッドでブロックされたり I/O が実行されたりすることはありません。 Swift 同時実行機能を使用して Realm への書き込みを実行する方法の詳細については、 「 アクターで Realm を使用する - Swift SDK 」を参照してください。
非対称オブジェクトの作成
バージョン 10.29.0 の新機能。
非対称オブジェクトはcreate(_ type:, value:)を使用してのみ作成できます。 AmetricObject を作成すると、 Data Ingestを介して Atlas App Services App にリンクされた Atlas データベースに一方向に同期されます。 AmetricObject にローカルでアクセスしたり、Realm に追加したり削除したり、クエリを実行したりすることはできません。
func useRealm(_ asymmetricRealm: Realm, _ user: User) async { try! asymmetricRealm.write { asymmetricRealm.create(WeatherSensor.self, value: [ "_id": ObjectId.generate(), "deviceId": "WX1278UIT", "temperatureInFahrenheit": 66.7, "barometricPressureInHg": 29.65, "windSpeedInMph": 2 ]) } }
Flexible Sync 構成で初期化された Realm 用の AmetricObjects を作成できます。 詳細については、「 Flexible Sync のために同期された Realm を開く 」を参照してください。
別の Realm へのオブジェクトのコピー
ある Realm から別の Realm にオブジェクトをコピーするには、元のオブジェクトを+[RMObject createInRealm:withValue:]に渡します。
RLMRealmConfiguration *configuration = [RLMRealmConfiguration defaultConfiguration]; configuration.inMemoryIdentifier = @"first realm"; RLMRealm *realm = [RLMRealm realmWithConfiguration:configuration error:nil]; [realm transactionWithBlock:^{ Dog *dog = [[Dog alloc] init]; dog.name = @"Wolfie"; dog.age = 1; [realm addObject:dog]; }]; // Later, fetch the instance we want to copy Dog *wolfie = [[Dog objectsInRealm:realm where:@"name == 'Wolfie'"] firstObject]; // Open the other realm RLMRealmConfiguration *otherConfiguration = [RLMRealmConfiguration defaultConfiguration]; otherConfiguration.inMemoryIdentifier = @"second realm"; RLMRealm *otherRealm = [RLMRealm realmWithConfiguration:otherConfiguration error:nil]; [otherRealm transactionWithBlock:^{ // Copy to the other realm Dog *wolfieCopy = [[wolfie class] createInRealm:otherRealm withValue:wolfie]; wolfieCopy.age = 2; // Verify that the copy is separate from the original XCTAssertNotEqual(wolfie.age, wolfieCopy.age); }];
ある Realm から別の Realm にオブジェクトをコピーするには、元のオブジェクトをRealm.create(_:value:update:)に渡します。
let realm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "first realm")) try! realm.write { let dog = Dog() dog.name = "Wolfie" dog.age = 1 realm.add(dog) } // Later, fetch the instance we want to copy let wolfie = realm.objects(Dog.self).first(where: { $0.name == "Wolfie" })! // Open the other realm let otherRealm = try! Realm(configuration: Realm.Configuration(inMemoryIdentifier: "second realm")) try! otherRealm.write { // Copy to the other realm let wolfieCopy = otherRealm.create(type(of: wolfie), value: wolfie) wolfieCopy.age = 2 // Verify that the copy is separate from the original XCTAssertNotEqual(wolfie.age, wolfieCopy.age) }
重要
create
メソッドは循環オブジェクト グラフの処理をサポートしていません。 直接または間接に親を参照するオブジェクトに関係する関係を含むオブジェクトは渡しません。