Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

CRUD - Atualização - Swift SDK

Nesta página

  • Atualizar Objetos de Realm
  • Sobre os exemplos nesta página
  • Atualizar um objeto
  • Atualizar Propriedades com Codificação de Chave-valor
  • Upsert de Objeto
  • Atualizar um Mapa/Dicionário
  • Atualizar uma propriedade MutableSet
  • Atualizar uma propriedade AnyRealmValue
  • Atualizar uma propriedade de objeto incorporado
  • Substituir um Objeto Integrado
  • Atualizar um Objeto Assincronamente
  • Atualizar propriedades por meio de projeções de classe
  • Alterar Propriedades de Projeção de Classe

As atualizações de objetos de Realm devem ocorrer nas transações de escrita. Para mais informações sobre as transações de escrita, consulte: Transações do .

Os exemplos nesta página usam os seguintes modelos:

// 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 Dog: Object {
@Persisted var name = ""
@Persisted var age = 0
@Persisted var color = ""
@Persisted var currentCity = ""
@Persisted var citiesVisited: MutableSet<String>
@Persisted var companion: AnyRealmValue
// 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?
}
class Address: EmbeddedObject {
@Persisted var street: String?
@Persisted var city: String?
@Persisted var country: String?
@Persisted var postalCode: String?
}

Você pode modificar as propriedades de um objeto de Realm dentro de uma transação de gravação da mesma maneira que atualizaria qualquer outro objeto de Swift ou Objective-C.

RLMRealm *realm = [RLMRealm defaultRealm];
// Open a thread-safe transaction.
[realm transactionWithBlock:^{
// Get a dog to update.
Dog *dog = [[Dog allObjectsInRealm: realm] firstObject];
// Update some properties on the instance.
// These changes are saved to the realm.
dog.name = @"Wolfie";
dog.age += 1;
}];
let realm = try! Realm()
// Get a dog to update
let dog = realm.objects(Dog.self).first!
// Open a thread-safe transaction
try! realm.write {
// Update some properties on the instance.
// These changes are saved to the realm
dog.name = "Wolfie"
dog.age += 1
}

Dica

Atualizar Objetos Relacionados e Integrados

Para atualizar uma propriedade de um objeto integrado ou de um objeto relacionado, modifique a propriedade com notação de ponto ou notação entre colchetes como se estivesse em um objeto aninhado regular.

Object, Result e List estão todos em conformidade com a codificação de valor-chave. Isto pode ser útil quando tiver que determinar qual propriedade atualizar no tempo de execução.

Aplicar KVC a uma coleção é uma ótima maneira de atualizar objetos em massa. Evite o custo de iterar sobre uma coleção ao criar acessadores para cada item.

let realm = try! Realm()
let allDogs = realm.objects(Dog.self)
try! realm.write {
allDogs.first?.setValue("Sparky", forKey: "name")
// Move the dogs to Toronto for vacation
allDogs.setValue("Toronto", forKey: "currentCity")
}

Você também pode adicionar valores para objetos integrados ou relacionados dessa maneira. Neste exemplo, adicionamos uma coleção à propriedade de lista de um objeto:

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^() {
// Create a person to take care of some dogs.
Person *ali = [[Person alloc] initWithValue:@{@"_id": @1, @"name": @"Ali"}];
[realm addObject:ali];
// Find dogs younger than 2.
RLMResults<Dog *> *puppies = [Dog objectsInRealm:realm where:@"age < 2"];
// Batch update: give all puppies to Ali.
[ali setValue:puppies forKey:@"dogs"];
}];
let realm = try! Realm()
try! realm.write {
// Create a person to take care of some dogs.
let person = Person(value: ["id": 1, "name": "Ali"])
realm.add(person)
let dog = Dog(value: ["name": "Rex", "age": 1])
realm.add(dog)
// Find dogs younger than 2.
let puppies = realm.objects(Dog.self).filter("age < 2")
// Give all puppies to Ali.
person.setValue(puppies, forKey: "dogs")
}

Um upsert insere ou atualiza um objeto dependendo de o objeto já existir. Os upgrades exigem que o modelo de dados tenha uma chave primária.

Para fazer o upsert de um objeto, chame -[RLMRealm addOrUpdateObject:].

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
Person *jones = [[Person alloc] initWithValue:@{@"_id": @1234, @"name": @"Jones"}];
// Add a new person to the realm. Since nobody with ID 1234
// has been added yet, this adds the instance to the realm.
[realm addOrUpdateObject:jones];
Person *bowie = [[Person alloc] initWithValue:@{@"_id": @1234, @"name": @"Bowie"}];
// Judging by the ID, it's the same person, just with a different name.
// This overwrites the original entry (i.e. Jones -> Bowie).
[realm addOrUpdateObject:bowie];
}];

Para inverter um objeto, chame Realm.add(_:update:) com o segundo parâmetro, política de atualização, definido como .modified.

let realm = try! Realm()
try! realm.write {
let person1 = Person(value: ["id": 1234, "name": "Jones"])
// Add a new person to the realm. Since nobody with ID 1234
// has been added yet, this adds the instance to the realm.
realm.add(person1, update: .modified)
let person2 = Person(value: ["id": 1234, "name": "Bowie"])
// Judging by the ID, it's the same person, just with a
// different name. When `update` is:
// - .modified: update the fields that have changed.
// - .all: replace all of the fields regardless of
// whether they've changed.
// - .error: throw an exception if a key with the same
// primary key already exists.
realm.add(person2, update: .modified)
}

Você também pode atualizar parcialmente um objeto passando a chave primária e um subconjunto dos valores para atualizar:

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
// Only update the provided values.
// Note that the "name" property will remain the same
// for the person with primary key "_id" 123.
[Person createOrUpdateModifiedInRealm:realm
withValue:@{@"_id": @123, @"dogs": @[@[@"Buster", @5]]}];
}];
let realm = try! Realm()
try! realm.write {
// Use .modified to only update the provided values.
// Note that the "name" property will remain the same
// for the person with primary key "id" 123.
realm.create(Person.self,
value: ["id": 123, "dogs": [["Buster", 5]]],
update: .modified)
}

Você pode atualizar um mapa de domínio como faria com um Dicionáriopadrão:

let realm = try! Realm()
// Find the dog we want to update
let wolfie = realm.objects(Dog.self).where {
$0.name == "Wolfie"
}.first!
print("Wolfie's favorite park in New York is: \(wolfie.favoriteParksByCity["New York"])")
XCTAssertTrue(wolfie.favoriteParksByCity["New York"] == "Domino Park")
// Update values for keys, or add values if the keys do not currently exist
try! realm.write {
wolfie.favoriteParksByCity["New York"] = "Washington Square Park"
wolfie.favoriteParksByCity.updateValue("A Street Park", forKey: "Boston")
wolfie.favoriteParksByCity.setValue("Little Long Pond", forKey: "Seal Harbor")
}
XCTAssertTrue(wolfie.favoriteParksByCity["New York"] == "Washington Square Park")

Você pode insert elementos em um MutableSet durante transações de gravação para adicioná-los à propriedade. Se estiver trabalhando com vários conjuntos, também é possível inserir ou remover elementos de um conjunto que estão contidos em outro conjunto. De forma alternativa, você pode silenciar um conjunto para conter apenas os elementos comuns de ambos.

let realm = try! Realm()
// Record a dog's name, current city, and store it to the cities visited.
let dog = Dog()
dog.name = "Maui"
dog.currentCity = "New York"
try! realm.write {
realm.add(dog)
dog.citiesVisited.insert(dog.currentCity)
}
// Update the dog's current city, and add it to the set of cities visited.
try! realm.write {
dog.currentCity = "Toronto"
dog.citiesVisited.insert(dog.currentCity)
}
XCTAssertEqual(dog.citiesVisited.count, 2)
// If you're operating with two sets, you can insert the elements from one set into another set.
// The dog2 set contains one element that isn't present in the dog set.
try! realm.write {
dog.citiesVisited.formUnion(dog2.citiesVisited)
}
XCTAssertEqual(dog.citiesVisited.count, 3)
// Or you can remove elements that are present in the second set. This removes the one element
// that we added above from the dog2 set.
try! realm.write {
dog.citiesVisited.subtract(dog2.citiesVisited)
}
XCTAssertEqual(dog.citiesVisited.count, 2)
// If the sets contain common elements, you can mutate the set to only contain those common elements.
// In this case, the two sets contain no common elements, so this set should now contain 0 items.
try! realm.write {
dog.citiesVisited.formIntersection(dog2.citiesVisited)
}
XCTAssertEqual(dog.citiesVisited.count, 0)

É possível atualizar uma propriedade AnyRealmValue por meio de atribuição, mas você deve especificar o tipo do valor ao atribuí-lo. O Realm Swift SDK fornece um enum AnyRealmValue que itera por todos os tipos que o AnyRealmValue pode armazenar.

let realm = try! Realm()
// Get a dog to update
let rex = realm.objects(Dog.self).where {
$0.name == "Rex"
}.first!
try! realm.write {
// As with creating an object with an AnyRealmValue, you must specify the
// type of the value when you update the property.
rex.companion = .object(Dog(value: ["name": "Regina"]))
}

Para atualizar uma propriedade em um objeto integrado, modifique a propriedade em uma transação de gravação. Se o objeto integrado for nulo, a atualização de uma propriedade dele não terá efeito.

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock: ^{
Contact *contact = [Contact objectInRealm:realm
forPrimaryKey:[[RLMObjectId alloc] initWithString:@"5f481c21f634a1f4eeaa7268" error:nil]];
contact.address.street = @"Hollywood Upstairs Medical College";
contact.address.city = @"Los Angeles";
contact.address.postalCode = @"90210";
NSLog(@"Updated contact: %@", contact);
}];
// Open the default realm
let realm = try! Realm()
let idOfPersonToUpdate = 123
// Find the person to update by ID
guard let person = realm.object(ofType: Person.self, forPrimaryKey: idOfPersonToUpdate) else {
print("Person \(idOfPersonToUpdate) not found")
return
}
try! realm.write {
// Update the embedded object directly through the person
// If the embedded object is null, updating these properties has no effect
person.address?.street = "789 Any Street"
person.address?.city = "Anytown"
person.address?.postalCode = "12345"
print("Updated person: \(person)")
}

Para substituir um objeto integrado, reatribua a propriedade do objeto integrado de uma parte a uma nova instância em uma transação de gravação.

RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock: ^{
Contact *contact = [Contact objectInRealm:realm
forPrimaryKey:[[RLMObjectId alloc] initWithString:@"5f481c21f634a1f4eeaa7268" error:nil]];
Address *newAddress = [[Address alloc] init];
newAddress.street = @"Hollywood Upstairs Medical College";
newAddress.city = @"Los Angeles";
newAddress.country = @"USA";
newAddress.postalCode = @"90210";
contact.address = newAddress;
NSLog(@"Updated contact: %@", contact);
}];
// Open the default realm
let realm = try! Realm()
let idOfPersonToUpdate = 123
// Find the person to update by ID
guard let person = realm.object(ofType: Person.self, forPrimaryKey: idOfPersonToUpdate) else {
print("Person \(idOfPersonToUpdate) not found")
return
}
try! realm.write {
let newAddress = Address()
newAddress.street = "789 Any Street"
newAddress.city = "Anytown"
newAddress.country = "USA"
newAddress.postalCode = "12345"
// Overwrite the embedded object
person.address = newAddress
print("Updated person: \(person)")
}

Você pode utilizar as funcionalidades de concorrência do Swift para atualizar objetos assincronamente usando um Realm isolado por atores.

Essa função do exemplo RealmActor definido na página Usar Realm com Atores mostra como você pode atualizar um objeto em um domínio isolado por atores:

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

E você pode fazer essa atualização usando a sintaxe assíncrona do Swift:

let actor = try await RealmActor()
// Read objects in functions isolated to the actor and pass primitive values to the caller
func getObjectId(in actor: isolated RealmActor, forTodoNamed name: String) async -> ObjectId {
let todo = actor.realm.objects(Todo.self).where {
$0.name == name
}.first!
return todo._id
}
let objectId = await getObjectId(in: actor, forTodoNamed: "Keep it safe")
try await actor.updateTodo(_id: objectId, name: "Keep it safe", owner: "Frodo", status: "Completed")

Esta operação não bloqueia nem executa E/S no thread de chamada. Para obter mais informações sobre como gravar no Realm usando os recursos de simultaneidade do Swift, consulte Use o Realm com atores — Swift SDK.

Você pode fazer alterações nas propriedades de uma projeção de classe em uma transação de gravação.

// Retrieve all class projections of the given type `PersonProjection`
// and filter for the first class projection where the `firstName` property
// value is "Jason"
let person = realm.objects(PersonProjection.self).first(where: { $0.firstName == "Jason" })!
// Update class projection property in a write transaction
try! realm.write {
person.firstName = "David"
}

Voltar

Leia

Próximo

Excluir