【问题标题】:Core Data many to many relation with intermediate table (Swift 2)Core Data 与中间表的多对多关系(Swift 2)
【发布时间】:2016-08-31 10:52:57
【问题描述】:

TL;DR EDIT with answer

正如韦恩完美回答的那样,这就是我现在获取信息的方式:

let ingredientsToRecipe = recipe.valueForKey("ingredientsToRecipe")! as! NSSet
for i in ingredientsToRecipe {
  print(i.valueForKey("amount")!)
  print(i.valueForKeyPath("ingredient.name")!)
}

原始问题

我在理解 CoreData 中中间表的使用方面存在很大问题。我搜索了 SO 的答案,发现了一些关于中间表和多对多关系的线程,但那些要么是 Objective-C,要么对我没有帮助。

我有以下设置(简化):

现在我想添加一个包含一堆配料的新食谱。 比方说一个汉堡。汉堡包括

  • 1个黄瓜,

  • 1 个番茄,

  • 1 肉,

  • 2 个面包

    (好吃...)

这是我迄今为止尝试过的:

// Core Data
let appDelegate =
  UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext
let entity = NSEntityDescription.entityForName("Recipe",
                                                inManagedObjectContext:managedContext)
// creating a new recipe with name and id
let recipe = NSManagedObject(entity: entity!,
                                 insertIntoManagedObjectContext: managedContext)
recipe.setValue("Burger", forKey: "name")
recipe.setValue("B_001", forKey: "id")

现在我得到了 Array:[NSManagedObject] 的成分(就像汉堡一样创建)和 Dictionary 的成分 ID。这就是我试图将我的食谱与配料结合起来的方式(在中间表上)。

for i in selectedIngredients { // the ingredient array
  let ingredientsToRecipe =     NSEntityDescription.insertNewObjectForEntityForName("RecipeIngredient", inManagedObjectContext: managedContext)
  
  ingredientsToRecipe.setValue(i, forKey: "ingredient")
  ingredientsToRecipe.setValue(recipe, forKey: "recipe")

  let quantity = Double(quantityDictionary[(i.valueForKey("id") as! String)]!) // the amount-to-ID dictionary
  ingredientsToRecipe.setValue("\(quantity)", forKey: "quantity")
}

最后我只是简单地保存了所有内容:

do {
  try managedContext.save()
  print("Saved successfully")
  self.dismissViewControllerAnimated(true, completion: nil)
} catch let error as NSError  {
  print("Could not save \(error), \(error.userInfo)")
}

以上所有这些都以某种方式起作用。但现在我正在努力获取有关我的食谱的信息。 我应该如何获取这个特定汉堡的西红柿数量?

类似的东西 recipe.valueForKey("RecipeIngredient").valueForKey("amount") 工作,但我不知道哪个量来自哪个成分。 我做错什么了吗? 我可以/应该做什么更好?

目标是创建一个包含成分的食谱,然后在表格中填充有关该食谱及其成分数量(以及成分本身)的信息。

感谢您的帮助!

【问题讨论】:

    标签: ios swift core-data


    【解决方案1】:

    您不需要使用valueForKeyvalueForKeyPath 来访问这些类型的属性...相反,您应该让Core Data 为您完成遍历关系的工作,并且只询问您需要什么使用点语法:

    for item in recipe.ingredientsToRecipe {
        print(item.amount)
        print(item.ingredient.name)
    }
    

    我建议您将中间实体从 IngredientsToRecipe (类似于数据库设计)重命名为 ItemsReceipeItems 以更好地捕捉它是什么 - 实际出现在配方中的项目,而不是基础食物类型本身。

    但无论你是否这样做,你都可以将 Receipe 上的关系命名为 items,从而提高可读性:

    for item in recipe.items {
        print(item.amount)
        print(item.ingredient.name)
    }
    

    您还可以更进一步,在名为 name 的中间实体上创建一个计算属性,该属性仅返回 ingredient.name,然后您可以使用:

    for item in recipe.items {
        print(item.amount)
        print(item.name)
    }
    

    :)

    【讨论】:

      【解决方案2】:

      要获取特定配方的成分数量,您可以使用如下谓词在 RecipeIngredient 创建获取请求:

      var request = NSFetchRequest(entityName: "RecipeIngredient")
      let predicate = NSPredicate(format: "recipe.name = %@ AND ingredient.name = %@", "burger","tomato")
      request.predicate = predicate
      

      然后您只需从返回的 RecipeIngredient 实体中获取数量值。

      【讨论】:

      • 感谢您的回答! @Wain 的回答更符合我的需求。
      【解决方案3】:

      中间对象的强大之处在于它把你的多对多关系分解成多个一对多关系。一对一的关系很容易导航。

      因此,从您的Recipe 中,您可以获得RecipeIngredients 的数组,对于每个数组,您可以获得valueForKey("amount")valueForKeyPath("ingredient.name")

      【讨论】:

      • 天哪,谢谢。我脑子里有这样一个障碍。这种方式就像一个魅力。虽然不能投票两次,但请感受一下拥抱!
      猜你喜欢
      • 2015-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 1970-01-01
      • 2016-04-07
      • 1970-01-01
      相关资源
      最近更新 更多