Seong Lee
Seong Lee

Reputation: 10580

Swift 2.1 Core Data - Save data that has one to many relationship but don't add isome data if already exists

I have a ViewController that creates a new recipe data. To create a new recipe, user will need to fill out title, ingredients etc along with selecting its category. And for that I have established Category and Recipe entities with One to Many relationship.

In the create function I will need to have the following search to see if Category Entity already has a value of selectedCategory.

if selectedCategory already exists in Category entity, I need to find its index and assign that category to Recipe Entity but I don't know what code I need to write here.

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

Upvotes: 1

Views: 460

Answers (1)

Mike Taverne
Mike Taverne

Reputation: 9362

I created a single view app with Core Data support.

I added two entities to the data model:

CategoryEntity has attribute "name". RecipeEntity has attribute "title".

CategoryEntity has an optional, many-to-one relationship to RecipeEntity called "recipes". It has a Cascade delete rule (if you delete a category, all related recipes are deleted, too).

RecipeEntity has a required, one-to-one relationship with CategoryEntity called "category".

These relationships are each the inverse of the other.

The following code adds a recipe. It gets or creates the category first, and assigns the recipe to it.

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

Upvotes: 1

Related Questions