21
votes

I've been using core data in my project for a while. Few days ago, I find that some of the records saved in database are not showing up in application UI. I've tracked it down and found that they're not being fetched at all when I filter out empty string using NSPredicate. And all of them starts with non-alphabetic characters.

To clarify the problem, I created a sample project and added a few sample data into database. Let's say they are "Sample", "+ sample", "Sample +".

Here's the code snippet I used to filter out empty string. "text" is the name of string property, and moc is NSManagedObjectContext instance.

NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"BasicEntity"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"text.length > 0"];
[request setPredicate:predicate];

NSArray *samples = [moc executeFetchRequest:request error:&error];

Result array contains only 2 entities, which are "Sample" and "Sample +".

I even tried same predicate(of course, using self.length instead of text.length) on simple array containing above sample strings, and I get all 3 correctly.

I wonder if anybody experienced same issue. Or am I missing something in using Core Data? Tested on iOS 7.0.3 simulator & 7.0.6 iPad Air.


UPDATE:As answered in another thread, I solved this issue by using regular expression.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"text MATCHES %@", @".{1,}"];

Still, I believe original predicate I used is a valid one. I'll file a bug to Apple to get their opinions.

2
@BenAvery Yes, using MATCHES can be a workaround. But I don't believe that sting's length property in NSPredicate is invalid. It does filter out entities with 0 length text, and works well with [NSArray filteredArrayUsingPredicate:]. I want to know if this is my misunderstanding, or I have to file a bug to Apple. - Wonjae
Try running the fetch without a predicate, and inspect the elements it returns. If it contains exactly all of the strings you were expecting, then the issue may be with the predicate. Otherwise the issue is probably with the encodings you are using to create the strings, prior to storing them in Core. - ryan cumley
@ryancumley It fetches every records without predicate. And, as I wrote above, same kind of predicate works well when filtering array. That's why I think this could be a bug in Core Data. I hard-coded sample strings in the code, so encoding might not be the case either. Anyway, thanks for your opinions. I'll file a bug to Apple to get some answers from Apple guys. - Wonjae
This guy has exactly cour problem: stackoverflow.com/questions/22767022/… Apparently it is forbidden to use Obj-C functions like length in your core data fetch request - JonEasy

2 Answers

4
votes

This is what you want

[NSPredicate predicateWithFormat:@"%K != %@", @"text", @""]

If you also need to check for nil / NULL do this:

[NSPredicate predicateWithFormat:@"%K != NULL && %K != %@", @"text", @"text", @""]
-3
votes

Try this:

NSPredicate *predicateName = [NSPredicate predicateWithFormat:@"name!=nil AND name!="""];