Docs Menu

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 {
@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 에 객체 를 추가하려면 다른 객체 와 마찬가지로 객체를 인스턴스화한 다음 쓰기 트랜잭션( 쓰기 트랜잭션 (write transaction) ) 내에서 -[RLMRealm addObject:] 영역 전달합니다.

// 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];
}];

영역에 객체를 추가하려면 다른 객체와 마찬가지로 객체를 인스턴스화한 다음 쓰기 트랜잭션(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) 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]]])

일부 속성 유형은 쓰기 트랜잭션(write transaction)에서만 변경할 수 있습니다. 예를 들어 MutableSet 속성을 사용하여 객체를 인스턴스화할 수 있지만 쓰기 트랜잭션(write transaction)에서는 해당 속성의 값만 설정할 수 있습니다. 쓰기 트랜잭션(write transaction) 내에서 초기화하지 않는 한 해당 속성의 값으로 객체를 초기화할 수 없습니다.

Realm 은 JSON 을 직접 지원 하지 않지만 JSONSerialization.jsonObject(with:options:) JSON 을 Realm.create(_:value: 업데이트:)에 전달할 수 있는 값으로 변환합니다.

// 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의 중첩된 객체 또는 배열을 일대일 또는 다대다 관계에 매핑합니다.

JSON 속성 이름과 유형은 대상 객체 스키마와 정확히 일치해야 합니다. 예시:

Realm은 객체 스키마에 정의되지 않은 JSON의 모든 속성을 무시합니다.

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

지도 속성 이 있는 객체를 만들 때 다음과 같은 몇 가지 방법으로 키 값을 설정할 수 있습니다.

  • 객체에 키와 값을 설정한 다음 객체를 영역에 추가

  • 쓰기 트랜잭션(write transaction) 내에서 직접 객체의 키와 값 설정

  • 키-값 코딩을 사용하여 쓰기 트랜잭션(write transaction) 내에서 키와 값을 설정 또는 업데이트

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에서는 지도 키에 . 또는 $ 문자를 사용할 수 없습니다. 백분율 인코딩 및 디코딩을 사용하여 허용되지 않는 문자 중 하나가 포함된 지도 키를 저장할 수 있습니다.

// Percent encode . or $ characters to use them in map keys
let mapKey = "New York.Brooklyn"
let encodedMapKey = "New York%2EBrooklyn"

다른 Realm 객체와 마찬가지로 MutableSet 속성을 포함하는 객체를 만들 수 있지만 쓰기 트랜잭션(write transaction) 내에서만 MutableSet를 변경할 수 있습니다. 이는 쓰기 트랜잭션(write transaction) 내에서 변경 가능한 설정 속성의 값만 설정할 수 있음을 의미합니다.

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 열거형 을 제공합니다.

추후 AnyRealmValue를 읽을 때는 값으로 어떤 작업을 수행하기 전에 유형을 확인해야 합니다.

// 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 사용 페이지에 정의된 RealmActor 예제의 함수는 행위자 격리 영역에 기록할 수 있는 방법을 보여줍니다.

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에 쓰는 방법에 대해 자세히 알아보려면 Actors와 함께 Realm 사용 - Swift SDK를 참조하세요.

버전 10.29.0의 새로운 기능

AsymmetricObject는 create(_ type:, value:) 를 통해서만 만들 수 있습니다. AsymmetricObject를 생성하면 데이터 수집 을 통해 Atlas App Services 앱에 연결된 Atlas 데이터베이스에 단방향으로 동기화됩니다. AsymmetricObject에 로컬로 액세스하거나 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에 대해 영역 를 생성할 수 있습니다. 자세한 내용 은 Flexible Sync를 위해 동기화된 Realm 열기를 참조하세요.

Realm 간에 객체 를 복사하려면 원본 객체 를 +[ 영역 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 메서드는 주기적 객체 그래프 처리를 지원하지 않습니다. 상위 항목을 직접 또는 간접적으로 참조하는 객체와 관련된 관계가 있는 객체를 전달하지 않도록 합니다.