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'.
Related
I need to set up my NSPredicate base on actual value stored in CoreDate.
Assuming we have a CoreData entity: "Graduate". we want to fetch graduate whose graduation date is earlier than Date1 if his/her graduation date is not null. Otherwise, I want to check if his/her birthday is earlier than Date2.
The predicate would look like this:
"if graduationDate != null graduationDate < %# else birthday < %#"
So I actually have two predicate. The second one should only come into effect if the field which first predicate wants to check is null.
My thoughts:
I can process this in my APP instead of CoreData, but just wonder is there a way to use only one NSPredicate to sort it out.
Some posts mentioned that NSPredicate is an equivalent to SQL Where Clause, which makes sense to me. And I think what I need here is going to beyond what Where Clause is capable of.
My question is not about how to filter fetch result using NSPredicate. It's about how to setup NSpredicate using a flow control like if else clause
You can use NSCompoundPredicate to combine smaller predicates.
let graduates = NSPredicate.init(format: "graduationDate != NULL AND graduationDate < %# ", graduationDate);
let oldPeople = NSPredicate.init(format: "graduationDate == NULL AND birthday > %# ", cutOffBirthday);
let predicate = NSCompoundPredicate.init(orPredicateWithSubpredicates: [graduates, oldPeople]);
I have two class, one is named Folder, the other is named Entry.
In my data model, a folder would contain multiple entry, and an entry can be contained by different folders.
So each folder has a folderID to identify itself, and a relationship named entries which is used to contains Entry instances. And each entry has an inverse relationship named superFolders which points back to the folder contains it.
Now is my question. Here I get a folderID. I want to use this and NSFetchRequest to fetch all the entries contained by this special folder in Core Data. The following is the main code:
let fetchRequest = NSFetchRequest<Entry>(entityName: "Entry")
fetchRequest.predicate = NSPredicate(format: "(ANY folder in %K).folderID = %i", #keyPath(Entry.superFolders), folerID)
The format string in above code is incorrect, but it mostly explain what I mean. Since superFolders property is actually a NSSet in Core Data, I can't use superFolders.folderID == %i as the judge condition. What exactly I want is to find all the entry whose superFolder property contains any of element which its folderID property match the given folderID.
So is that possible to use NSPredicate to express what I mean to Core Data ?
You want:
let fetchRequest = NSFetchRequest<Entry>(entityName: "Entry")
fetchRequest.predicate = NSPredicate(format: "ANY superFolders.folderID = %#", folderID)
See the NSPredicate reference
If you had a more complicated match on the superFolders relationship, you would need to use SUBQUERY, but in this case a simple ANY predicate works fine.
I have 3 core data entities.
MenuItems, Items, ItemLangs.
All entities has iItemId attribute. The user need to search using sItemName which can be found in the ItemLangs.
The UITableView contains array of MenuItems.
I have tried filteredArrayUsingPredicate but my predicate is not right. Do I need to loop through the array of MenuItems first before I can filter the array?
Here is my predicate:
NSPredicate *resultPredicate = [NSPredicate
predicateWithFormat:#"sItemName LIKE %#", searchText];
May I know how can I use this to filter the array of MenuItems that I have?
Thank you!
What you need is a predicate like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"sItemName CONTAINS[cd] %#", searchText];
[cd] stands for case insensitiveness.
Alternately, if you like "LIKE", refer to this answer.
UPDATE:
You should also look at the data item you want to fetch - sItemName in your case. Through debugger, inspect what object does your data source array return? I am referring to the array you want to apply the above predicate to. Maybe there is some keypath hierarchy involved in getting through towards sItemName, in which case you need to use dot notation, such as Items.ItemLangs.sItemName.
Refer following links, it may help you:
1) How to implement SearchBar and search display controller in tableview in xib
2) first attempt at synamic filtering a search array
3) http://www.appcoda.com/search-bar-tutorial-ios7/
4) http://www.raywenderlich.com/16873/how-to-add-search-into-a-table-view
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];
Im building an app where users will be able to filter through a set of photos based on 4 parameters:
model http://seismicdevelopment.com/shot.png
FeedType and PhotoType can be one of three possible values respectively. Market and Tag can contain multiple values that describe the photo. I have the ui setup where for FeedType/PhotoType is a series of UISwitches for each param. If you turn one value on, the others in that group will turn off.
Market/Tag have UIButtons that can be made selected/normal. Any selected button should be added to the filtering to narrow results.
I can't seem to figure out how I should write the filtering logic to be most effective. Essentially on any control change, I need to rewrite the predicate filter but I can't seem to wrap my head around how I can link the separate param filters together.
For Tag/Market I'd also like to add a disabled state for UIButtons that have no records, or no records based on the currently selected buttons.
It is hard to tell a precise advice without knowing what kind the parameters are, but, as far as i can see, you need to have four variables,more likely,NSStrings, and every time the user changes the parameter, you create a new fetch predicate, by appending all that variables with the right format. That's how i see it in general.
UPDATE
So, with Market and Tag Butons everything is quite obvious - you shoud use NSCompondPredicate. You'll need an array of predicates, so make a property.
#property (strong) NSMutableArray *subpredicates;
Then, each time user touches the button, you add or remove that narrowing predicate.
- (void)tagButtonTouched:(UIButton *)button
{
if (thisTagIsNotYetSelected)
[subpredicates addObject:[NSPredicate predicateWithFormat:#"ANY tags.name == %#", button.titleLabel.text]];//or some other predicate based on that button title
else
[subpredicates removeObject:[NSPredicate predicateWithFormat:#"ANY tags.name == %#",button.titleLabel.text] ]];
}
Same thing for Markets
- (void)marketButtonTouched:(UIButton *)button
{
if (thisMarketIsNotYetSelected)
[subpredicates addObject:[NSPredicate predicateWithFormat:#"ANY markets.name == %#", button.titleLabel.text]];//or some other predicate based on that button title
else
[subpredicates removeObject:[NSPredicate predicateWithFormat:#"ANY markets.name == %#",button.titleLabel.text] ]];
}
You should also add two variables,i guess,NSPredicates or NSString,that will hold the value of selected FeedType and PhotoType,lets's call them feedTypePredicate and photoTypePredicate respectivly. When user touches those switches(why not segmentedControls?), you just change their's values.
And, finally, you should just combine all those predicates into one and make your fetch!
if(photoTypePredicate)
[subpredicates addObject:photoTypePredicate];
if(feedTypePredicate)
[subpredicates addObject:feedTypePredicate];
NSPredicate *finished = [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];//Your final predicate