Docs Menu
Docs Home
/ /
Atlas Device SDK
/ /

CRUD - 作成 - Swift SDK

項目一覧

  • 新しいオブジェクトの作成
  • このページの例について
  • オブジェクトの作成
  • 値のあるオブジェクトを初期化
  • JSON によるオブジェクトの作成
  • 埋め込みオブジェクトの作成
  • マップ プロパティを持つオブジェクトの作成
  • MutableSet プロパティを持つオブジェクトの作成
  • 任意の RealmValue プロパティを持つオブジェクトの作成
  • オブジェクトの非同期作成
  • 非対称オブジェクトの作成
  • 別の Realm へのオブジェクトのコピー

このページの例では、次のモデルを使用します。

// 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 {
@Persisted var name = ""
}
class Dog: Object {
@Persisted var name = ""
@Persisted var age = 0
@Persisted var color = ""
@Persisted var currentCity = ""
@Persisted var citiesVisited: MutableSet<String>
@Persisted var companion: AnyRealmValue
// To-one relationship
@Persisted var favoriteToy: DogToy?
// Map of city name -> favorite park in that city
@Persisted var favoriteParksByCity: Map<String, String>
}
class Person: Object {
@Persisted(primaryKey: true) var id = 0
@Persisted var name = ""
// To-many relationship - a person can have many dogs
@Persisted var dogs: List<Dog>
// Embed a single object.
// Embedded object properties must be marked optional.
@Persisted var address: Address?
convenience init(name: String, address: Address) {
self.init()
self.name = name
self.address = address
}
}
class Address: EmbeddedObject {
@Persisted var street: String?
@Persisted var city: String?
@Persisted var country: String?
@Persisted 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プロパティを使用してオブジェクトをインスタンス化できますが、そのプロパティの値は書込みトランザクション内でのみ設定できます。 書込みトランザクション内で初期化しない限り、そのプロパティの値でオブジェクトを初期化することはできません。

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"

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)")

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 に追加したり削除したり、クエリを実行したりすることはできません。

@MainActor
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 にオブジェクトをコピーするには、元のオブジェクトを+[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メソッドは循環オブジェクト グラフの処理をサポートしていません。 直接または間接に親を参照するオブジェクトに関係する関係を含むオブジェクトは渡しません。

戻る

CRUD