5

I have a simple method that uses NSPredicate to return the number of rows where comments.length > 0.

Problem is, I found that when the Comment column starts with + - * or /, the length property always evaluates to 0, and thus the row is excluded from the count.

I opened the table in SQLite browser and verified the column is a VARCHAR. Using a SQLite query to check string length works just fine (LENGTH(ZComments) > 0), so this must be a CoreData issue.

Here is my function...

-(int)getCommentsCount{
    NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
    [request setIncludesSubentities:YES];
    [request setEntity:[NSEntityDescription entityForName:@"InspectionRecord" inManagedObjectContext:managedObjectContext]];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(comments.length > 0)"];
    [request setPredicate:predicate];

    NSError *err;
    NSUInteger count = [managedObjectContext countForFetchRequest:request error:&err];

    //count is ALWAYS 0 if 'comments' starts with + - * or /     WHYYY???      
    return count;
}

I was able to work around this by checking for empty/null string instead of using .length, but I'd really like to know why .length fails when the string starts with certain characters.

Has this happened to anyone?

Hal Mueller
  • 7,019
  • 2
  • 24
  • 42
iupchris10
  • 453
  • 3
  • 14
  • Not the cause of your error, but method signature should be `-(NSUInteger)commentsCount`. Match the return type of `-countForFetchRequest:error:`, and don't start method names with `get` unless they return multiple items indirectly ([Cocoa Naming Conventions](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CodingGuidelines/Articles/NamingMethods.html#//apple_ref/doc/uid/20001282-BCIGIJJF)). – Hal Mueller Mar 31 '14 at 17:03

1 Answers1

10

You cannot use Objective-C functions like length in a Core Data fetch request (and the ".length" part is simply ignored when Core Data translates the fetch request to a SQLite query). But you can simply compare with an empty string instead:

 [NSPredicate predicateWithFormat:@"comment != ''"]

For other queries involving the length, you can use the MATCHES operator with a regular expression as shown here: CoreData predicate: string property length?.

Community
  • 1
  • 1
Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • 1
    Additionally, the reason that using `.length` might appear to work sometimes is that Core Data will translate `comments.length > 0` to SQL as something like `t0.ZCOMMENTS > 0`, losing the "length" part of the query. **That** seems like a bug to me, but that's how it is for the moment. I don't know how SQLite evaluates strings in a `> 0` comparison, but it's not what's implied by `comments.length`. – Tom Harrington Mar 31 '14 at 17:26
  • Great explanation, thanks! I even verified this by changing ".length" to ".foo" and got the same results. Is there a legitimate way to compare length of string using NSPredicate? Furthermore.... someone better tell the people on this other thread that they are doing things wrong.... http://stackoverflow.com/questions/7369390/nspredicate-to-test-for-null-and-blank-strings – iupchris10 Mar 31 '14 at 18:23
  • 1
    @iupchris10: "comment.length > 0" and similar *does work* when e.g. filtering arrays. It fails only for Core Data fetch requests (and that is already mentioned in one comment to the answer). – Martin R Mar 31 '14 at 18:29
  • 1
    @iupchris10: Other string length comparisons can be done with regular expressions (as in the answer that I linked to). – Martin R Mar 31 '14 at 18:32
  • @MartinR - thanks. I also just stumbled upon this thread, which suggests adding a length property to your managed object, and setting it whenever the text value is changed. - [link]http://stackoverflow.com/questions/3644621/nspredicate-for-an-nsmanagedobjects-string-attributes-length – iupchris10 Mar 31 '14 at 18:37