Why doesn't this NSPredicate work? - iphone

I have a very simple NSPredicate as such:
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"name beginswith '%#'", theString];
[matchingTags filterUsingPredicate:sPredicate];
This causes the array to have 0 results when theString == "p"
However, when I do this:
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"name beginswith 'p'"];
[matchingTags filterUsingPredicate:sPredicate];
I get over 100 results, as expected.
I have checked "theString" with NSLog() and its value is correct. I feel like I am missing some crucial secret. Possibly because I am using a string and not a character?
Thoughts?

Check out the documentation here
If you use variable substitution using
%# (such as firstName like %#), the
quotation marks are added for you
automatically.
So basically, it's looking for names that start with "p", instead of p. Changing your code to:
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"name beginswith %#", theString];
should work

Related

Searching 2 Attributes at the same time CoreData

I'm trying to use a predicate to search 2 attributes at the same time. I initially tried a compound predicate but it would only return results if both predicates matched the string.
Basically I'm looking for something similar to this:
let predicate = NSPredicate(format: "title CONTAINS[cd] %#" || "plainTextBody CONTAINS[cd] %#", searchString, searchString)
So it seems I was close with my original post but it's important to keep the search terms in quotation marks and not separate them like I did in my original question. Simply using the following works perfectly:
let predicate = NSPredicate(format: "title CONTAINS[cd] %# || plainTextBody CONTAINS[cd] %#", searchString, searchString)

NSPredicate for searching a string with double quotes

An attribute element in coredata model is a string(json string format), which is an array of dictionaries like below,
one element has
"[{"tagName":"sad","count":2},{“tagName":"happy","count":1}]"
and other has
"[{"tagName":"sad1","count":2},{“tagName":"happy1","count":1},{“tagName":"nothappy","count":1}]"
Need to search the list with refer to the tagname.
If I use the predicate below,
tagName = "sad"
tagNameFilter += String(format: "vrTags CONTAINS[cd] \"%#\"", tagName)
it's returning both elements. It should return the first element alone
If I use without double quotes
tagName = "sad"
tagNameFilter += String(format: "vrTags CONTAINS[cd] %#", tagName)
it's crashing with reason:
unimplemented SQL generation for predicate : (vrTags CONTAINS[cd] sad) (LHS and RHS both keypaths) with userInfo of (null)
If I use
tagName = "sad"
tagNameFilter += String(format: "vrTags CONTAINS[cd] \"\"%#\"\"", tagName)
it's crashing with reason: Unable to parse the format string
How to solve this filter issue? Any suggestions would be appreciated.
In order to search for a string "sad" including the quotation marks you have to pass that string with the quotation marks as an argument to NSPredicate(format:). This can be done with with string interpolation:
let tagName = "sad"
let predicate = NSPredicate(format: "vrTags CONTAINS[cd] %#", "\"\(tagName)\"")
print(predicate) // vrTags CONTAINS[cd] "\"sad\""
And never use String(format:) and string concatenation to build complex predicates. That is very error-prone because the quoting and escaping rules for predicate strings are different from those to format strings.
If you need to combine multiple conditions with “AND” then do it like
let p1 = NSPredicate(...)
let p2 = NSPredicate(...)
// ...
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [p1, p2, ...])

Fetch request not working in Swift 4.1 [duplicate]

This question already has answers here:
Xcode 9.3 - NSPredicate Bool crash
(3 answers)
Closed 4 years ago.
I have a predicate that is a Bool set to false (mostly). It stopped working correctly in Swift 4.1 when I upgraded yesterday.
The predicate is:
requestData.predicate = NSPredicate(format: "delete == %#", false as CVarArg);
How do I check if this value is false in the Core Data store? Thanks.
The placeholder %# is for objects, the placeholder for a Bool is %d
However there is a simpler syntax if the argument is a constant
requestData.predicate = NSPredicate(format: "delete == FALSE")
You should get your predicate working by using:
requestData.predicate = NSPredicate(format: "delete == NO")
Unfortunately I can't tell you why your example with CVarArg did stop working - but since it is not needed in your example I would try using the other initializer with the optional argumentArray parameter: init(format:argumentArray:)
The documentation in section Boolean Values says:
You specify and test for equality of Boolean values as illustrated in the following examples:
NSPredicate *newPredicate =
[NSPredicate predicateWithFormat:#"anAttribute == %#", [NSNumber numberWithBool:aBool]];
NSPredicate *testForTrue =
[NSPredicate predicateWithFormat:#"anAttribute == YES"];

How to sort ckrecords by userID?

How should I go about creating an nspredicate that checks the userID of a record in swift?
let userID = "__defaultOwner__"
let predicate = NSPredicate(format: "keyToUseHere == %#", userID)
What should I put in place of the 'keyToUseHere' in the nspredicate to sort by the creator's id?
You need to use the key which can be property of your model class something like this:-
let predicate = NSPredicate(format: "userID" == %#", userIDValue)

create a Compound Predicate in coreData xcode iphone

HI i am working on the core data with 3 entities (Class,Students,ExamRecord) and their relations area as :
Class<------>> Students <------> ExamRecord
I created a predicate for fetching list of students for class 5th.
NSString * fmt2 = #"studentsToClass.className=%#";
NSPredicate * p2 = [NSPredicate predicateWithFormat:fmt2,#"5th",nil];
with this i am getting all students of class 5th
Now i also want to apply another filter on the Students fetched.
Fetch students whose Exam Record "result" is "Pass".result is an attribute for student in ExamResult entity
How can i make use of Compound predicate in this ?
Please correct me if i am wrong
Any help will be appreciated
Thanks
You can use a compound predicate:
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"studentsToClass.className = %#", #"5th"];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"studentsToExamRecord.result = %#", #"Pass"];
NSPredicate *p = [NSCompoundPredicate andPredicateWithSubpredicates: #[p1, p2]];
Or you simply combine the tests with "AND":
NSPredicate *p = [NSPredicate predicateWithFormat:#"studentsToClass.className = %# AND studentsToExamRecord.result = %#",
#"5th", #"Pass"];
Note that the argument list of predicateWithFormat is not nil-terminated.
The number of arguments is determined by the number of format specifiers in the format
string.
First, you shouldn't really call the student - class relation studentsToClass. The name of the relation should reflect what type of object is at the other end.
E.g.
In this case the Student relation to Class should be called class because the object there is a single Class entity.
The inverse relation should not be called classToStudent it should be called students because the object there is a NSSet of multiple Students.
EDIT
Just to add to this. The name of the relation should explain WHY it is there. We can see that the relation is from class to student but if you call it "classToStudent" it doesn't explain anything. Also, what if you have a second relation from class to student? What do you call that. If you call it attendees or pupils or attendingStudents etc.. it gives the relation meaning.
SOLUTION
In this example I'm going to call them how I would call them and you will see it makes it a bit easier to understand...
Anyway...
NSPredicate *classPredicate = [NSPredicate predicateWithFormat:#"class.className = %#", #"5th"];
NSPredicate *passPredicate = [NSPredicate predicateWithFormat:#"result.name = %#", #"Pass"];
NSCompoundPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[classPredicate, passPredicate]];
First, your quoted predicate is really already wrong. You should reference the managed object, not its property (i.e. not the name of the Class). It should be:
[NSPredicate predicateWithFormat:#"class = %#", classObject];
Also, you should really choose more readable names for your variables and property. So, not fmt2 but formattingString. Not studentsToClass but form ("class" is a special word in objective-C). You get the idea.
So your desired compound predicate is done like this (short version):
[NSPredicate predicateWithFormat:#"class = %# && record.result = %#",
classObject, #"Pass"];
The complicated version, if you really need a higher level of abstraction (which I doubt):
classPredicate = [NSPredicate predicateWithFormat:#"class = %#", classObject];
resultPredicate = [NSPredicate predicateWithFormat:#"record.result = %#", #"Pass"];
finalPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:
#[classPredicate, resultPredicate]];
Predicates can also be nested using compounded predicates (For Swift)
let orPredicate = NSCompoundPredicate(type: .or, subpredicates: [date_1KeyPredicate, date_2KeyPredicate])
let functionKeyPredicate = NSPredicate(format: "function_name = %#", self.title!)
let andPredicate = NSCompoundPredicate(type: .and, subpredicates: [orPredicate, functionKeyPredicate])