CoreData: Fetch an object that has a given property AND a given relationship? - core-data

I have a CoreData model that looks a bit like this:
Object A:
Results -- A one to many relationship to an indeterminate number of Object B's.
Object B:
Object Name -- A string. (potentially not unique)
Parent -- A singular relationship with Object A.
I am struggling with writing a NSPredicate that will return ObjectB if I know a given Object A and the Object Name string I am looking for. I have tried the following, but always get this error:
"'NSInvalidArgumentException', reason: 'Unable to parse the format string ..."
request.predicate = [NSPredicate predicateWithFormat:#"NameString == %#, SELF IN %#", NameString, ObjectA.results];
request.predicate = [NSPredicate predicateWithFormat:#"(NameString == %#) IN %#", NameString, ObjectA.results];
And so on...
This seems like this should be a simple and obvious thing to do, but I am new at Core Data and am having trouble finding an example that shows this.
Thanks!

You need to use %K.
You may need something like this in your predicate
NSString enitity=#"ObjectA";
NSString attribute=#"results";
request.predicate = [NSPredicate predicateWithFormat:#"NameString == %#, SELF IN %K.%K", NameString, enitity,attributes];
Look here.

Related

NSFetchRequest predicate querying correctly, but resulting NSManagedObject showing incorrect fields [duplicate]

I am using UIManagedDocument with Parent Child context.
In my child context I do the following
Code 1
NSSet *results = [self.event.memberships filteredSetUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return ([[evaluatedObject deleted] boolValue] == NO);
}]];
Above code returns the expected results (only Not deleted members for the event).
Code 2
But this code does not. It fetches all records.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"deleted == NO"];
NSSet *results = [self.event.memberships filteredSetUsingPredicate:predicate];
It seems confusing. Both should return same results, but predicateWithBlock returns correct results where as predicateWithFormat returns all records.
What are the pros and cons of using predicateWithBlock instead of predicateWithFormat?
The problem is that you have defined an attribute deleted for your entity. That conflicts with the isDeleted method of NSManagedObject, so you should rename that attribute.
The following "experiment" shows that strange things happen if you call your attribute "deleted" (c is a managed object with a custom deleted attribute):
// Set custom "deleted" property to YES:
c.deleted = #YES;
// Use the property, as your Code 1
NSLog(#"%#", [c deleted]);
// Output: 1
// Use Key-Value Coding, as your Code 2
NSLog(#"%#", [c valueForKey:#"deleted"]);
// Output: 0
// Now really delete the object and try again:
[context deleteObject:c];
NSLog(#"%#", [c valueForKey:#"deleted"]);
// Output: 1
Your "Code 1" refers to the property, therefore it returns the expected result. "Code 2" uses Key-Value Coding, and [c valueForKey:#"deleted"] returns YES if the object
actually has been deleted from the context!
So renaming that attribute should solve your problem. Unfortunately the compiler does not
emit warnings if an attribute name conflicts with a built-in method.
Use the formatting placeholder to replace the bool value:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K == %#",
#"deleted", #(NO)];
Your use of the key path is probably ok, but the right-hand side probably doesn't look like "NO" to the parser.

Creating Core Data predicate to get data within one-to-many relationship

I have a Loans entity with a returnedDate attribute that can contain a date or be NIL. There is a to-many relationship with another entity, Items such that items can be related to many Loans. I would like to create a predicate where I can find all items that do not currently have a loans.returnedDate==NIL.
Assume I currently have the following:
Loan1-item1,returnedDate=NIL
Loan2-item1,returnedDate=5/4/2012
Loan3-item2,returnedDate=NIL.
I would like a predicate that returns no items.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"!(ANY loaned.returnDate==nil)"];
Returns item1.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(NONE loaned.returnDate==nil)"];
Returns item1.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"(ANY loaned.returnDate!=nil)"];
Returns item1.
Can someone tell me what logic would return the appropriate results?
So I used the following predicate:
(SUBQUERY(loaned, $sub, $sub.returnDate==nil).#count == 0)
and it is returning the desired results. If you can convince me not to use SUBQUERY, please tell me how.

Core Data NSPredicate casting key value

I have a data model which has values of type id that I was planning on casting appropriately when needed.
Is it possible for me to cast these as strings and compare them to strings from a UISearchBar using NSPredicate or do I have to use another method?
Maybe something like this:
NSPredicate * predicate;
predicate = [NSPredicate predicateWithFormat:#"CAST(%K) contains[cd] %#", employeeID , theSearchBar.text];
No. The CAST() function doesn't work that way. I think you just have to assume that the id returned from -employeeID is comparable to a string.

Predicate Problem when fetching objects in a To-Many relationship

I have a simple situation where I have two entities related with Many-To-Many relationship.
Two objects, Alarms and Tags. When I want to fetch all the Alarms associated with a given Tag, I tried this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%# IN tags", theTag];
What I get is all Alarms, not just those related to the Tag.
However, trying this the other way around works:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF in %#", theTag.alarms];
For complicated reasons having to do with code reuse, I really need the first one to work. Any help would be much appreciated! Thanks!
If you have a Tag object, then you can get all of its alarms by doing:
NSSet *alarms = [theTag alarms];
If for some bizarre reason you have to do this with a fetch request (which you shouldn't), your predicate should be:
NSPredicate *p = [NSPredicate predicateWithFormat:#"tags CONTAINS %#", theTag];

How can I use NSPredicate to filter on core data relationships?

Say I have core data objects of type "obj" that has a property "propertyA" and a one-to-many relationship with an object of type "sub" that has two properties, "propertyB" and "propertyC".
I want to fetch all the objs that have propertyA equal to a value and a sub obj with propertyB and propertyC set.
If it was just propertyA and propertyB, I would do
[NSPredicate predicateWithFormat:#"ANY sub.propertyB = %# AND propertyA == %#", ...];
The problem is that I can't figure out how to add in the second property. I want only the objs that have at least one sub that has the two properties true. I've tried the following, but it doesn't work:
[NSPredicate predicateWithFormat:#"ANY (sub.propertyB = %# AND sub.propertyC) AND propertyA == %#", ...];
I've tried it without the ANY but that doesn't work either. How can I do this?
Since you have a to-many relationship with the sub object, the subs property of obj returns a set instead of a single object. To query the set, you need to use a SUBQUERY.
Subqueries have the form:
SUBQUERY(collection, $individualCollectionItem, expression-with-collection-item)
in this case you would want something like
SUBQUERY(subs,$s,$s.propertyB==%#) AND SUBQUERY(subs,$s,$s.propertyC!=NULL)
The solution seems to be:
[NSPredicate predicateWithFormat:#"propertyA == %# AND (SUBQUERY(sub, $s, $s.propertyB == %# AND $s.propertyC == %#).#count != 0)", propertyAvalue, propertyBvalue, propertyCvalue];
where the values at the end are the values you want the various properties to be equal to.

Resources