Filter Core Data objects by relationship

1.2k views Asked by At

I have two objects: Category and Item. An Item has a name field, price field, and quantity field. A Category has a name field. A category also has many Items. When I access my tableView of categories I want to display all the items related to that category. Below is my code of how I'm setting the relationship when a new Item is added and also when a category is fetched to display all its items. Am I not saving the relationship correctly?

Saving Relationship

func saveItem(name: String, quantity: Int, price: String) {
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext!
    let entity =  NSEntityDescription.entityForName("Item", inManagedObjectContext: managedContext)
    let item = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
    var error: NSError?

    item.setValue(name, forKey: "name")
    item.setValue(quantity, forKey: "quantity")
    item.setValue(price, forKey: "price")
    item.setValue(selectedCategory, forKey: "category")
    // selectedCategory: the parent of this new item
    selectedCategory.setValue(NSOrderedSet(object: item), forKey: "item")
    if !managedContext.save(&error) {
        println("Could not save \(error), \(error?.userInfo)")
    }
    else {
        items.append(item)
        self.fetchCategories("")
    }
}

fetching items of category

func fetchItems() {
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    let managedContext = appDelegate.managedObjectContext!
    let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
    let fetchRequest = NSFetchRequest(entityName: "Item")
    fetchRequest.sortDescriptors = [sortDescriptor]
    fetchRequest.predicate = NSPredicate(format: "category = %@", category?.valueForKey("name") as! String)
    var error: NSError?
    let fetchedResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as? [NSManagedObject]

    if let results = fetchedResults {
        items = results

    }
    else {
        println("Could not fetch \(error), \(error!.userInfo)")
    }
}

my data model

enter image description here enter image description here

1

There are 1 answers

0
pbasdf On

Because the item relationship is the inverse of the category relationship, you do not need to set both. If you set the relationship one way, Core Data automatically does the other:

item.setValue(selectedCategory, forKey: "category")

So the following lines are not required...

// selectedCategory: the parent of this new item
selectedCategory.setValue(NSOrderedSet(object: item), forKey: "item")

Also your predicate is wrong in the fetch - there is no need to use the name attribute in the predicate - CoreData will (under the hood) use its own primary key. So amend this:

fetchRequest.predicate = NSPredicate(format: "category = %@", category?.valueForKey("name") as! String)

to this:

fetchRequest.predicate = NSPredicate(format: "category = %@", category!)