【问题标题】:Swift Realm - Iterate an array of items to update their relationshipsSwift Realm - 迭代一组项目以更新它们的关系
【发布时间】:2021-08-04 21:15:08
【问题描述】:

我与 Realm Schema 上的关系表有一个基本的多对多关系。 所以我有Recipe、Ingredient和RecipeIngredient模型。

当我尝试创建一个食谱时,我必须迭代一个成分数组来创建食谱成分。创建 recipeIngredient 后,我​​想编辑我的食谱和我的成分以添加与新 RecipeIngredient 的关系。但是成分的版本抛出异常,我不知道为什么......

这里有一些代码

配方模型

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

成分模型

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

配方成分模型

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

配方表单模型

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

创建配方逻辑

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

createRecipe 方法上的这一行抛出异常:ingredient.ingredient.recipeIngredients.append(recipeIngredient)

这里的错误信息:Terminating app due to uncaught exception 'RLMException', reason: 'Cannot modify managed RLMArray outside of a write transaction.' 但是我有写块...

有什么想法吗?

【问题讨论】:

  • 我会知道是哪一行引发了错误。请逐行检查您的代码以确定这一点并使用信息更新问题。
  • 谢谢。我在代码中提到过,这一行在 create recipe 方法中抛出了错误ingredient.ingredient.recipeIngredients.append(recipeIngredient)。我会更新我的问题
  • 如果我在看这个,for ingredient in form.ingredients 正在迭代 form 中的成分,class RecipeForm: ObservableObject 不是 Realm 对象。所以你想将非领域对象添加到领域?或者也许还有更多。
  • 你是对的 form,不是一个领域对象,但它包含一个 QuantifiedIngredient 数组,其中包含一个 ingredient 这是一个领域对象,这就是我这样做的原因ingredient.ingredient(领域对象).recipeIngredients.append()
  • 所以这个ingredient.ingredient.recipeIngredients. 解析为QuantifiedIngredient.ingredient.recipieIngredients,对吧?那么QuantifiedIngredient 是什么,它是否由同一个领域管理,和/或它是一个领域对象?

标签: ios swift realm


【解决方案1】:

似乎当我尝试在成分上添加 recipeIngredient 时,我实际上尝试将领域对象放在领域成分的副本上。所以显然不行,但是错误信息不是很清楚。

为了修复它,我使用了thaw()函数,它返回了好的领域对象,所以我可以编辑它。

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

我不知道这是否是最好的方法,所以如果有人有更好的选择,我会听 :)

【讨论】:

  • 你应该只 thaw() 那些被 freeze() 的对象,否则你会有奇怪的行为。 冻结的对象不是实时的,也不会自动更新。它们实际上是冻结时对象状态的快照。解冻对象会返回冻结对象的实时版本。
猜你喜欢
  • 1970-01-01
  • 2017-10-27
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2022-07-20
  • 1970-01-01
  • 2022-01-16
相关资源
最近更新 更多