MJQZ1347 MJQZ1347 - 1 year ago 284
Swift Question

Realm / iOS: How to query for String AND NSDate property?

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?


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?

Answer Source

If you want to filter using a predicate, you need to pass a predicate and not just a string as the argument.

Why "chatId == '\(self.chatId!)' AND date > \(date)" doesn't work is that the compiler interprets this only as a string 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 filter(:_) or just move the instantiation to inside the method:

newMessages = self.realm.objects(Message).filter(NSPredicate(format: "chatId = %@ AND date > %@", self.chatId!, date))

Another way is to use the filter(_:) method as such:

let newMessages = self.realm.objects(Message).filter({ $0.chatId == self.chatId! && $0.date.compare(dateToCompare) == NSComparisonResult.OrderedDescending })