Reputation: 22
I am trying to make my realm objects able to edit from the app. This is my class:
import Foundation
import RealmSwift
class Category: Object {
@objc dynamic var name: String = ""
let items = List<Item>()
}
this is how I make instances of that class:
let action = UIAlertAction(title: "Add", style: .default) { action in
let newCategory = Category()
newCategory.name = textField.text!
self.save(category: newCategory)
}
this is my edit method:
func edit(category: Category) {
do {
try realm.write {
realm.add(category, update: .all)
}
}catch {
print("error editing category \(error)")
}
}
and this is how I call my edit method inside IBAction for when edit button pressed
let saveAction = UIAlertAction(title: "Save Changes", style: .default) { action in
let editedCategory = Category()
editedCategory.name = textField.text!
self.edit(category: editedCategory)
}
the error I am getting is: "Terminating app due to uncaught exception 'RLMException', reason: ''Category' does not have a primary key and can not be updated'"
I have tried adding the primary key in my category class, but is still did not work. Any help?
Upvotes: 0
Views: 1733
Reputation: 35648
A lot of this is covered in the Realm guide Read and Write Data but let me also provide some details. Note, this answer reflects Swift pre-10.10.0 and some things have changed in later versions.
The method you're trying to use
realm.add(category, update: .all)
is called an 'upsert' and requires a primary key in the object.
An upsert either inserts or updates an object depending on whether the object already exists. Upserts require the data model to have a primary key.
So let's re-tool the Category object to include a primary key _id
class Category: Object {
@objc dynamic var _id: ObjectId = ObjectId.generate()
@objc dynamic var name: String = ""
let items = List<Item>()
override static func primaryKey() -> String? {
return "_id"
}
}
Then, when an object is created
let newCategory = Category()
newCategory.name = textField.text!
let realm = try! Realm()
try! realm.write {
realm.add(newCategory)
}
it will have a primary key
From then forward you can either modify the object within a write or upsert it via it's primary key.
let someId = //the id of the newCategory created above
try! realm.write {
let anotherCat = Category(value: ["_id": someId, "name": "Frank"])
realm.add(anotherCat, update: .modified)
}
The above code will update the original newCategory object with a new name because the _id is the same
Upvotes: 1