Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fetch core data relationships in one single NSFetchRequest?

Tags:

I have a core data app with the model setup just like the image below:

Core Data Model

The relationships are setup like this:

Category<-->>Subcategory<-->>Item

Now, is it possible in one single fetch to get objects from Subcategory and Item entities that have the same attribute called categoryName? I think it can be done by using relationships, but the code I am using is not working which is:

let fetchNote = NSFetchRequest(entityName: "Category")
    fetchNote.predicate = NSPredicate(format: "ANY subcategory.name == %@ AND item.name == %@", "Badaue", "Badaue")
    let notes = try! appDel.managedObjectContext.executeFetchRequest(fetchNote) as? [Category]
    print(notes)
like image 286
Marco Almeida Avatar asked Jun 02 '16 14:06

Marco Almeida


People also ask

How can you retrieve data from Core Data?

Fetching Data From CoreData We have created a function fetch() whose return type is array of College(Entity). For fetching the data we just write context. fetch and pass fetchRequest that will generate an exception so we handle it by writing try catch, so we fetched our all the data from CoreData.

Is it possible to have relationship in Core Data?

Inverse relationships enable Core Data to propagate change in both directions when an instance of either the source or destination type changes. Every relationship must have an inverse. When creating relationships in the Graph editor, you add inverse relationships between entities in a single step.

What are fetched properties in Core Data?

Fetched Properties in Core Data are properties that return an array value from a predicate. A fetched property predicate is a Core Data query that evaluates to an array of results.

What is a Core Data relationship?

Persistent storage has become an essential part of the majority of iOS apps nowadays. Core Data is a persistence and/or in-memory cache framework that consists of a very powerful set of other tools that can be used within the app.


2 Answers

To avoid confusion, I'd suggest renaming item to items to reflect that it's a to-many relationship. Same goes for subcategory.

EDIT2 - You are asking to get the Subcategory and Item objects that have a certain categoryName, correct? The query you've written above doesn't do that at all.

First, yes, you will need 2 queries, as you can only fetch 1 Entity type at a time.

Second, let's re-write your syntax because right now it's super dangerous.

do {
  let predicate = NSPredicate(format: "categoryName == %@", "yourCategoryHere")
  let fetchSubcategory = NSFetchRequest(entityName: "Subcategory")
  fetchSubcategory.predicate = predicate
  if let subCategoryResults = try context.executeFetchRequest(fetchSubcategory) as? [Subcategory] {
    //do stuff
  }
  let fetchItem = NSFetchRequest(entityName: "Item")
  fetchItem.predicate = predicate
  if let itemResults = try context.executeFetchRequest(fetchItem) as? [Item] {
    //do stuff
  }
}catch {
  print(error)
}
like image 125
sschale Avatar answered Sep 28 '22 01:09

sschale


If you fetch Categories you will get an array of Category objects. Each of those objects will have a property, subcategory, which is a set containing all the related Subcategory objects. And each of those objects will have a property, item, which is a set containing all the Item objects related to that Subcategory. The related objects are "nested" within the Category and Subcategory objects.

When you fetch the Categories, you do not need to specify a predicate to get the related objects. They will be automatically fetched as soon as you access the subcategory or item properties. So, for example, if myCategory is a Category object you have fetched,

let mySubcategories = myCategory.subcategory
for subcat in mySubcategories {
    print("\(subcat)")
}

should print each of the related subcategories.

If those properties are nil, it might be that you have not yet established the relationships. That is normally done when you first create the objects. For example, if you create a Subcategory with categoryName = "Badaue", you might establish the relationship with the Category with name = "Badaue" like this:

let newSubcategory = ....
newSubcategory.categoryName = "Badaue"
let fetchCategory = NSFetchRequest(entityName: "Category")
fetchCategory.predicate = NSPredicate(format: "name == %@", newSubcategory.categoryName)
let categories = try! appDel.managedObjectContext.executeFetchRequest(fetchNote) as? [Category]
if (categories!.count > 0) {
    let firstCategory = categories[0]
    newSubCategory.category = firstCategory
} else {
    // no existing Category with the correct name, so create one....
    let newCategory = ....
    // ... and then establish the relationship to the Subcategory
    newSubCategory.category = newCategory
}
like image 30
pbasdf Avatar answered Sep 28 '22 01:09

pbasdf