Reputation: 90
I have a basic many-to-many relation with a relation table on my Realm Schema. So I have Recipe, Ingredient and RecipeIngredient model.
When I try to create a Recipe, I have to iterate an array of Ingredient to create RecipeIngredient. Once the recipeIngredient is create I want to edit my Recipe and my Ingredient to add a relation to the new RecipeIngredient. But the edition of the Ingredient throws an exception, and I have no idea why...
Here some code
Recipe Model
class RecipeRealm: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var name: String = ""
@Persisted var lastEditedTime: Date = Date()
@Persisted var recipeIngredients: List<RecipeIngredient>
convenience init(name: String){
self.init()
self.name = name
}
}
Ingredient Model
class IngredientRealm: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var name: String = ""
@Persisted var unit: Unit = Unit.none
@Persisted var lastEditedTime: Date = Date()
@Persisted var recipeIngredients: List<RecipeIngredient>
convenience init(name: String){
self.init()
self.name = name
}
}
RecipeIngredient Model
class RecipeIngredient: Object, ObjectKeyIdentifiable {
@Persisted(primaryKey: true) var _id: ObjectId
@Persisted var qty: Int = 0
@Persisted var lasEditedTime: Date = Date()
@Persisted(originProperty: "recipeIngredients") var recipe: LinkingObjects<RecipeRealm>
@Persisted(originProperty: "recipeIngredients") var ingredient: LinkingObjects<IngredientRealm>
}
The recipe form model
struct QuantifiedIngredient {
var ingredient: IngredientRealm
var qty: Int16
}
class RecipeForm: ObservableObject {
@Published var name = ""
@Published var ingredients: [QuantifiedIngredient] = []
var recipeID: String?
var updating: Bool {
recipeID != nil
}
init(){}
init(_ recipe: Recipe){
name = recipe.name ?? ""
ingredients = []
recipeID = recipe.id
}
}
The create Recipe logic
private func createRecipe() {
withAnimation {
do {
let realm = try Realm()
// Create Recipe on RealmDB
let realmRecipe = RecipeRealm(name: form.name)
try realm.write{
realm.add(realmRecipe)
for ingredient in form.ingredients{
let recipeIngredient = RecipeIngredient()
recipeIngredient.qty = Int(ingredient.qty)
realm.add(recipeIngredient)
realmRecipe.recipeIngredients.append(recipeIngredient)
ingredient.ingredient.recipeIngredients.append(recipeIngredient) // <--- this line crash
}
}
} catch {
print(error.localizedDescription)
}
presentationMode.wrappedValue.dismiss()
}
}
An exception is throw by this line on createRecipe method: ingredient.ingredient.recipeIngredients.append(recipeIngredient)
.
Here the error message: Terminating app due to uncaught exception 'RLMException', reason: 'Cannot modify managed RLMArray outside of a write transaction.'
But I have the write block...
Any ideas ?
Upvotes: 0
Views: 597
Reputation: 90
It seems that when I tried to add recipeIngredient on the ingredient, I actually tried to put a realm object on a copy of the realm ingredient. So is obviously not working, but the error message is not very clear.
To fix it I used the thaw()
function that returns me the good realm object, so I can edit it.
try realm.write{
realm.add(realmRecipe)
for ingredient in form.ingredients{
let recipeIngredient = RecipeIngredient()
recipeIngredient.qty = Int(ingredient.qty)
realm.add(recipeIngredient)
realmRecipe.recipeIngredients.append(recipeIngredient)
guard let rIngredient = ingredient.ingredient.thaw() else {
return
}
rIngredient.recipeIngredients.append(recipeIngredient)
}
}
I don't know if this is the best way to do it, so if someone had a better option I'm listening :)
Upvotes: 1