NSPredicate a relationship objects - ios

i'm working with core data and i've two tables
List
ListItems
ListItems has a relationship named "parentlist" with destination set to "List"
I'm trying to query the ListItems for all the listItems whoes parent is X (List object)
i've tried this approach but it's not working
List* myList; // Initialized form other views
NSPredicate *pred = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"List == %#",myList]];

If you have an inverse relationship listItems (as Apple recommends) you can use just:
myList.listItems

There are two problems in your code: In the predicate you have to use the relationship ("parentList"),
not the target entity ("List"). And you should not mix string formatting with
predicate formatting.
To get all ListItems related to the given list, the predicate would be
List* myList = ...;
NSPredicate *pred = [NSPredicate predicateWithFormat:#"parentList == %#", myList];

I'm assuming you're looking for something other than simply accessing the listItems through the list? If so :
comparing objects in core data doesn't really work that way.
You could do this in one of two ways,
Easy : Assign the lists a GUID on creation using :
[[NSProcessInfo processInfo] globallyUniqueString]
and use this for comparing two lists.
Harder : implement a comparison function on the objects by overriding compare and compare the objects in a way that makes sense to you.
- (NSComparisonResult) compare : (List *) other;
Then create a NSPredicate using blocks.
You could also use a GUID and use it in the compare function, thus allowing you to expand on this later.

Related

NSPredicate count on a relationship attribute

I have actually a core data entity called Show and for every show I have a relation ship called Schedule that contains an attribute called schedules which is an array.
What I want to do is to create a Predicate that checks for a given show's schedule if it has more than 1 item.
To do That I tried Two solutions :
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"schedule.schedules > 1];
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"schedule.schedules.#count > 1];
But None of them would work.
NB : schedules attribute is an stored in my Core Data as Transformable and declared as an id variable.
A transformable attribute is stored as binary data, and it isn't unpacked until the container entity is loaded into memory. So, you can't use any kind of predicate based on a transformable attribute in a fetch. It will only work to filter the results of the fetch.
Cheap solution is to store a simple integer attribute with the count and use that.
Better solution is likely to add / change your entities so you use a relationship instead of a transformable.
Did you try this?
NSPredicate * predicate = [NSPredicate predicateWithFormat:#"#count.schedule.schedules > 1];

Using NSFetchRequest with complex NSPredicate in a NSFetchRequestController

Im trying to implement something that I'm sure have been implemented a million times before, a search in the core data database, displayed in a table using a fetchRequestController and the searchController.
My problem is writing the NSPredicate for the NSFetchRequest. According to the NSPredicate guide by Apple, not everything you can do in Sqlite is possible with core data.
I have been trying to find a solution for some time, but maybe one of you can use his experience to help me.
CoreData DB description:
Shops has a MANY TO MANY relationship with DiscountProgam.
My use case is as follows: I need to filter out Shops who's name/address/zip/city contains the search string. that's the easy part.
The hard part is creating the section of the database I want to filter from, because I have an array of "active" discountPrograms UID's, and I only want shops that have one of the active discount programs in their "discountPrograms" set. So in pseudo code that would be:
FROM Shops who have at least one discountProgram who's uid IN activeDiscountProgramsArray WHERE name/address/zip/city CONTAINS searchString
Is this possible? am I over reaching the limits of predicates?
If so, how could I do it differently?
Yes, NSPredicate can analyse both the direct attributes of the target entity of a fetch and the attributes of its relationships. Try:
NSArray *validUIDs = ...;
NSString *searchTerm = ...;
[NSPredicate predicateWithFormat:#"(name CONTAINS[cd] %# OR zip CONTAINS[cd] %#) AND (SUBQUERY(discountProgram, $d, $d.UID IN %#).#count > 0)", searchTerm, searchTerm, validUIDs];

Queries with Mobile Services Azure iOS

I am trying to write a query that gets a row when the id is equal to 1 (at the moment).
NSPredicate *predicate = [NSPredicate predicateWithFormat:[apt[#"id"] isEqualToNumber:1]];
So where id (from another database) is equal to 1. Now this is complaining all sorts of things but its saying it needs to be a BOOL. Is NSPredicate needing a BOOL?
Not sure I understand, or is there another way I can query? Can I use T-SQL in Mobile Services SDK Azure for iOS?
The predicate with format expects a string, you are sending in a bool. [apt[#"id"] isEqualToNumber:1] returns a bool.
Use the predicate in this manner (I have little experience with formatting predicates, so this will likely not actually work for you to copy and paste in).
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"id == 1"];
This will work if your objects in the array you are filtering have a property called id.
Something I understand a littler better is predicates with blocks. This could work for you too (I'm not entirely sure of your data structure, so you are gong to have to modify to suit your needs.
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
return [object[#"id"] isEqualToNumber:1]; // Return YES for each object you want in filteredArray.
}]

"IN" NSPredicate where the search is made within an array of objects

I have an array called deletedDepartments which contains NSObjects called DeletedObject. A DeletedObject only has a field called deletedID. This array is generated from a mapping with RestKit.
Now, I want to search within CoreDate for Department objects where their id is within the deletedDepartments array.
If I do
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:#"id IN %#", deletedDepartments ]];
This won't work because deletedDepartments is not a NSArray made of NSNumber, but of NSObject which contains the NSNumber I want to compare. How can I achieve such thing without creating another array made from iterating over the deletedDepartments and selecting only the deletedID?
Change your predicate to the following :
[NSPredicate predicateWithFormat:#"deletedID IN %#", [deletedDepartments valueForKey:#"deletedID"]]
This will create an array of your deletedId's, and evaluate each object using the deletedId property. While, yes, this does internally iterate over the array to create a new one, that's the best you can do unless the NSObjects in deletedDepartments are of the same class as the model objects that your are fetching.

NSPredicate/TableView only displays one item, why?

I'm working on an app where I have two entities, Post <-->> StreamType. When I create posts I assign StreamType:s like this:
// streamType == one of my default streamTypes
[post addStreamTypesObject:streamType];
My predicate for finding posts that have a certain StreamType looks like this:
predicate = [NSPredicate predicateWithFormat:#"ANY streamTypes.type = %#", [NSNumber numberWithInt:self.pageType]];
I'm not sure why this happens. Any ideas?
Edit
What I basically want is to fetch all Posts that have the right StreamType. Seemed after all that my fetchrequest only returns 1 item from the database. So probably nothing wrong with my tableview.
Edit 3
The problem was with my relationship, should be many-to-many, not one to many. Therefore it only returned one Post item.
First: test if the other code is ok. Simply, remove the predicate (comment the setPredicate line). You should see ALL objects in your tableview.
Right?
Second: check if self.pageType is set correctly. I don't see in your code how you set self.pageType
Test your predicate, add an NSLog like this and check if the result is ok:
NSLog(#"ANY streamTypes.type = %d", self.pageType);
Third:
As far as I understand, you have this situation:
One Post has only one stream type
One stream type has multiple posts.
The ANY keyword is used in situations where you want, for example, obtain all stream types where a particular condition is satisfied at least one time. for example (assuming you have a "content" instance variable on your post, containing the text of the post)
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY post.content CONTAINS[cd] %#", #"aWord"];
In this case, you will obtain all stream types in which there are posts containing "aWord" particular word in the text.
Your case is simpler. I think that you should simply use:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"streamTypes.type = %d", self.pageType];
Try and let me know
I was just having the same issue using Core Data with Swift and just wanted to add this answer in incase anybody else is having a similar issue.
This was my NSPredicate code:
let predicate = NSPredicate(format: "routine == %#", self.selectedRoutine)
Routine holds multiple exercise objects which I was trying to return. An exercise can only have one routine but a routine can have many exercises.
Turns out I'd forgotten to select 'To Many' as the relationship type for the exercises relationship in my routine entity using the Data Model inspector. It was set as 'To One'.

Resources