How to query for String AND NSDate property? - ios

I am facing an odd error with my code:
if let date = self.messages.last?.date {
let newMessages = self.realm.objects(Message).filter("chatId == '\(self.chatId!)' AND date > \(date)")
}
This outputs the error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "chatId = 'oSgUGWH9fWURmBh5NQZK2POpxdI3yEdl7PrPzAU33l7cVFIpzR38otF3' AND date > 2016-07-17 10:56:07 +0000"'
What am I doing wrong?
EDIT:
Using NSPredicate it works:
let predicate = NSPredicate(format: "chatId = %# AND date > %#", self.chatId!, date)
newMessages = self.realm.objects(Message).filter(predicate)
But why doesn't the first solution work?

If you want to filter an array using a predicate, you need to pass a predicate and not just a string literal as the argument, and also use the method filteredArrayUsingPredicate(_:).
Why "chatId == '\(self.chatId!)' AND date > \(date)" doesn't work is that the compiler interprets this as a string literal - and not a predicate as you've created in your other example:
NSPredicate(format: "chatId = %# AND date > %#", self.chatId!, date)
The fix is to either instantiate an NSPredicate as you've done in your edit, and pass that value to filteredArrayUsingPredicate(:_) or just move the instantiation to inside the method:
newMessages = self.realm.objects(Message).filteredArrayUsingPredicate(NSPredicate(format: "chatId = %# AND date > %#", self.chatId!, date))
If you want to use this method, the array needs to be an NSArray, and the objects in the array need to be KVC compliant, so you're better off in Swift with using the filter(_:) method as such:
let newMessages = self.realm.objects(Message).filter({ $0.chatId == self.chatId! && $0.date.compare(date) == NSComparisonResult.OrderedDescending })

Related

Swift Core Data NSPredicate static string issue

I would like to make predicate more flexible for changes. I have lot of such strings in the sources code:
let predicate = NSPredicate(format: "bodyPart.name = %#", name)
let filteredExercises = ExerciseEntity.mr_findAll(with: predicate)
but as you see if I will change BodyPart name to MuscleGroup for example someday it will cause issue like:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath bodyPart.name not found in entity <NSSQLEntity ExerciseEntity id=5>'
I am searching for the solution with a key paths like
let predicate = NSPredicate(format: "%# = %#", \BodyPart.name, name)
Use %K to substitute the key path
let predicate = NSPredicate(format: "%K = %#", #keyPath(BodyPart.name), name)

NSPredicate crash after swift 3 migration

after migration to swift3, I have an issue that cannot fix
let fetchRequest: NSFetchRequest<User> = User.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "id == %#", id)
my App crashes on second line, bad access, no reason. types are right, no log, nothing, just bad access. any suggestions?
Found a reason, predicate is wrong, cause id is Int64 type, have no idea what kind of predicate I need for this version of swift
The %# format expect a Foundation object as argument, compare
"Predicate Format String Syntax" in the "Predicate Programming Guide".
You can bridge the Int64 to NSNumber:
let id = Int64.max
let predicate = NSPredicate(format: "id == %#", id as NSNumber)
print(predicate) // id == 9223372036854775807
or change the format to "long long":
let id = Int64.max
let predicate = NSPredicate(format: "id == %lld", id)
print(predicate) // id == 9223372036854775807
Bridging all number types to NSNumber is possible as of Swift 3.0.1 (Xcode 8.1) with the implementation of
SE-0139 Bridge Numeric Types to NSNumber and Cocoa Structs to NSValue.

can´t understand fetchRequest.predicate

I´ve a quite "simple" predicate for a NSFetchRequest:
guard let kategorie = self.fetchedResultsController.objectAtIndexPath(indexPath) as? Kategorien else {
return
}
let fetchRequest = NSFetchRequest(entityName: "Details")
fetchRequest.predicate = NSPredicate(format: "kategorie == %i", kategorie.katid!)
do {
let results = try self.managedObjectContext.executeFetchRequest(fetchRequest) as! [Details]
...
The content of the sqllite-"table" is
the content of the variables are
So from
fetchRequest.predicate = NSPredicate(format: "kategorie == %i", kategorie.katid!)
i get the Predicate
kategorie == 18
while
kategorie.katid is 1
I can´t understand it :-(
Any help???
That's really strange, but you can just do:
NSPredicate(format: "kategorie = \(kategorie.katid!)")
And then you don't need to worry about whether you need a %i, or a %ld, or a %#, etc...
katid is an (optional) NSNumber, and what happens in your case
is that the (lower 32-bit of the) address of the object is taken as an integer.
The correct format
specifier is %# (for instances of NSObject subclasses):
NSPredicate(format: "kategorie == %#", kategorie.katid!)
Alternatively, convert the object to an integer:
NSPredicate(format: "kategorie == %d", kategorie.katid!.intValue)
Of course, forced unwrapping should be avoided, e.g.
NSPredicate(format: "kategorie == %d", kategorie.katid?.intValue ?? 0)
Using string interpolation in the format string (as suggested by
#Gargoyle) is another solution in this special case of numbers,
but not generally: If you interpolate a string then any percent
character will be interpreted as a format specifier and that leads
to unexpected output or crashes. Also single or double quotes will
lead to problems because these have a special meaning in predicate
format strings.

'Unable to parse the format string "claimID != '' & userID = %#"'

I am trying to write a NSPredicate to fetch userID and claimID and I am getting the below error.
Terminating app due to uncaught exception NSInvalidArgumentException', reason: 'Unable to parse the format string "claimID != '' & userID = %#"'
My Code is-
+(NSArray*)fetchNotificationsWithPredicate {
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"claimID != '' & userID = %#",[[NSUserDefaults standardUserDefaults] objectForKey:#"usernmae"]];
NSLog(#"%#",[self fetchNotifications]);
NSArray *loginUsers = [DBUtils createAndExecuteFetchRequestWithPredicate:#"Notification" predicate:predicate];
return loginUsers;
}
Looking at the predicate string format, it looks like & isn't a valid operator. You either want AND or &&. So:
#"claimID != '' && userID = %#"
or
#"claimID != '' AND userID = %#"
(This may well not be the only issue. I've never used this API, and I'm not an iOS developer. This is just from inspection of the documentation...)
Rewrite your predicate:
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"claimID != '' AND userID MATCHES %#",[[NSUserDefaults standardUserDefaults] objectForKey:#"usernmae"]];
Note: for number matching use '=' and for string matching use 'MATCHES'

swift NSPredicate compare string

In the twitter api, the id_str is like this: "572581876033982465".
Right now I want to use NSPredicate to filter the tweets, and the current format is like this:
NSPredicate(format: "idStr > %#", self.maxId!)
Both idStr and self.maxId are type of String. And it crashes with error message: "Operator type 2 not supported for string type".
I think it means that I should cast both of them to number value.
I tried this:
let predicate = NSPredicate(format: "[idStr intValue] > %#", self.maxId!.toInt()!)
But it crashes with error:
Unable to parse the format string "[idStr intValue] > %#
How to cast the id_str in the format?
Have you tried this:
let id_str = "572581876033982465"
let id_num = id_str.toInt()!
var predicate = NSPredicate(format: "id_num > %#", self.maxId!.toInt()!)

Resources