Swift 2.1 Core Data - 保存具有一对多关系的数据,但如果已经存在则不要添加异构数据
Posted
技术标签:
【中文标题】Swift 2.1 Core Data - 保存具有一对多关系的数据,但如果已经存在则不要添加异构数据【英文标题】:Swift 2.1 Core Data - Save data that has one to many relationship but don't add isome data if already exists 【发布时间】:2016-04-01 01:50:29 【问题描述】:我有一个创建新配方数据的 ViewController。 要创建新食谱,用户需要填写标题、成分等以及选择其类别。为此,我建立了具有一对多关系的 Category 和 Recipe 实体。
在创建函数中,我需要进行以下搜索以查看类别实体是否已经具有 selectedCategory 的值。
如果 selectedCategory 已经存在于 Category 实体中,我需要找到它的索引并将该类别分配给 Recipe Entity 但我不知道我需要在这里编写什么代码。
for category in categories
if category == selectedCategory
/* if selectedCategory already exists in Category entity,
find its index and assign that category to Recipe entity.*/
else
category.name = selectedCategory
recipe.category = category
context.insertObject(recipe)
do
try context.save()
catch
print("Could not save recipe")
【问题讨论】:
如何将类别与 selectedCategory 进行比较,并将 category.name 属性设置为 selectedCategory?类别是什么类型的对象? 你用什么来选择类别?UIPickerView
。假设UIPickerView
有5个元素(类别),当用户选择甜点== 2(使用委托获取索引)时,插入category.type = @2
并插入新食谱recipe.name = "someName"
,最后将食谱添加到类别[category addRecipe: recipe]
,然后保存上下文。
我正在使用 tableview 来选择类别。 Category 对象具有 name 属性,默认情况下它将包含 Main、Side、Dessert、Drink 等值。用户可以添加自定义类别名称,但我必须防止插入重复的名称。
您可以使用NSFetchRequest
并在其上设置NSPredicate
。当用户输入类别名称时,在将值设置为category.name
属性之前,使用谓词将字符串值与保存的Category
实体匹配。执行 fetch 请求时,如果结果计数为 0,则将其保存为新类别,否则将其保存到执行 fetch 时返回的 managedObject 中。
【参考方案1】:
我创建了一个支持 Core Data 的单视图应用程序。
我在数据模型中添加了两个实体:
CategoryEntity 具有属性“名称”。 RecipeEntity 具有属性“title”。
CategoryEntity 与 RecipeEntity 有一个可选的多对一关系,称为“recipes”。它有一个级联删除规则(如果你删除一个类别,所有相关的配方也会被删除)。
RecipeEntity 与 CategoryEntity 具有必需的一对一关系,称为“类别”。
这些关系彼此相反。
以下代码添加了一个配方。它首先获取或创建类别,然后将配方分配给它。
import UIKit
import CoreData
class ViewController: UIViewController
@IBOutlet weak var category: UITextField!
@IBOutlet weak var recipeTitle: UITextField!
@IBAction func createRecipe(sender: AnyObject)
// Apple's out of the box Core Data app exposes a managedObjectContext on the appDelegate, so we'll use it here
if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate
// we have to have a category name ...
if let categoryName = category.text
// ... and a recipe title
if let recipeTitle = recipeTitle.text
// get the category to associate this recipe with
let categoryEntity = obtainCategoryEntity(categoryName, context: appDelegate.managedObjectContext)
// create the recipe entity
let recipeEntity = (NSEntityDescription.insertNewObjectForEntityForName("RecipeEntity", inManagedObjectContext: appDelegate.managedObjectContext) as! RecipeEntity)
// assign the recipe to the category
// note that you set up relationships in Core Data by assigning entities,
// not indexes or id fields
recipeEntity.category = categoryEntity
// set the recipe's title
recipeEntity.title = recipeTitle
// save it!
do
try appDelegate.managedObjectContext.save()
NSLog("saved context")
catch let error as NSError
NSLog("failed to save context with error \(error)")
catch
fatalError()
func obtainCategoryEntity(name: String, context: NSManagedObjectContext) -> CategoryEntity
// this function gets or creates a category entity
let fetchRequest = NSFetchRequest(entityName: "CategoryEntity")
fetchRequest.predicate = NSPredicate(format: "name == %@", name)
//find existing category, if it exists
if let results = (try? context.executeFetchRequest(fetchRequest)) as? [CategoryEntity]
if results.count > 0
// we really should only ever have one match, so return it
return results[0]
//category did not exist, so create it
let categoryEntity = NSEntityDescription.insertNewObjectForEntityForName("CategoryEntity", inManagedObjectContext: context) as! CategoryEntity
// set the category name
categoryEntity.name = name
// return it, but don't save it here - let the save later take care of it
return categoryEntity
【讨论】:
感谢您抽出时间来演示这一点。它工作得很好。现在我知道 NSPredicate 可用于搜索现有记录。以上是关于Swift 2.1 Core Data - 保存具有一对多关系的数据,但如果已经存在则不要添加异构数据的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Swift 中的 Core Data 中保存多个项目