I have a core data app with the model setup just like the image below:
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)
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.
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.
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.
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.
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)
}
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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With