iOS Core Data how to properly compare string text using predicates?

13,198

Solution 1

A single equal sign is not even a comparator in terms of coding.

I'm going to assume unique is an NSManagedObject attribute.

[NSPredicate predicateWithFormat:@"unique LIKE %@", uniqueValue];

Note that this is case-sensitive. If you want to make it insensitive, then you can put [c] after the LIKE.

Solution 2

I don't see a problem with your predicate. A single = is perfect if you want to match exact strings. If you don't need wildcard matching you don't need the slower LIKE. (Predicate Format String Syntax)

However, there is a problem in your code, and it might lead you to assumptions that are not correct. Your if/then/else, or at least the first message is kind of wrong. If you fetch does not return an array it means the fetch failed, it does not mean that the fetch didn't return objects.

It should be more like this:

if (!matches)
{
    NSLog(@"Error: couldn't execute fetch request %@", error);
}
else if([matches count] > 1) {
    NSLog(@"Error: More than one object for unique record");
    returnValue = YES;
} else if ([matches count] == 0) {
    NSLog(@"couldn't match objects");
    returnValue = NO;
} else {
    // [matches count] == 1
    NSLog(@"matched one object");
    returnValue = YES;
}

Oh, and I would change the order of the conditions. In my opinion a structure like (!matches), ([matches count] == 1), ([matches count] == 0), (else) makes more sense and it's easier too read. You put the most important (because it is what you actually want) condition in the last "anonymous" else.

Share:
13,198
Alex Stone
Author by

Alex Stone

When people asked me what I wanted to do for work 10 years ago, I did not know too well, so I just said "Something to do with computers". As I look at the last 10 years, I see that I did quite a lot of work all kinds of computers. From fiddling with microcontrollers and assembler code to writing data processing scripts to physically assembling computer consoles. The big step forward came when I learned to think about software in a structured, object-oriented way, as this allowed me to make software do things that I want it to do. Right now I'm proficient in two high level programming languages - Objective-C and Java and have touched just about every framework available for iOS. I've also became a hacker/maker and have completed a number of projects involving software and hardware. Right now I'm in my early 30s and when I ask myself "What would I like to do in the next 10 years?", my answer is "something with the human brain". The seeds are already there - I've picked up an interest in biology, cognitive science and neuroscience, enough to converse with real people. I've done first-hand research into sleep and made discoveries. I've taken classes in synthetic biology, performing manipulations on the bacteria genome. I've learned a lot about the neurotransmitter systems of the human brain, as well as how a biological organism develops. It seems like there are a lot of similarities between the object-oriented concepts I use in the daily programming tasks and how biological organisms operate. This makes me hopeful that by the time I'm in my late 30s, I would be able to work and program some form of biological computer or just plain hack the human brain.

Updated on June 17, 2022

Comments

  • Alex Stone
    Alex Stone almost 2 years

    This is literally driving me nuts.

    I have 2 entities that use NSStrings as unique attribute.

    What is the correct way to create a predicate that compares NSStrings?

    Currently I have: [NSPredicate predicateWithFormat:@"unique= %@", uniqueValue];

    I have a feeling that this compares the pointer addresses, not actual string values, but I cannot confirm that. I need to return yes for an exact string match.

    -(BOOL)uniqueEntityExistsWithEnityName:(NSString*)entityName UniqueKey:(NSString*) uniqueKey UniqueValue:(NSString*)uniqueValue SortAttribute:(NSString*)sortDescriptorAttribute ManagedObjectContext:(NSManagedObjectContext*) context;
    {
        BOOL returnValue = NO;
    
        NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName];
    
    //what is the correct predates to compare the text an string core data property against a passed in string?
        request.predicate = [NSPredicate predicateWithFormat:@"unique= %@", uniqueValue];
    
        NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:sortDescriptorAttribute ascending:YES];
        request.sortDescriptors = [NSArray arrayWithObject:sortDescriptor];   
    
        NSError *error = nil;
        NSArray *matches = [context executeFetchRequest:request error:&error];
        if (!matches)
        {
             NSLog(@"Error: no object matches");
        }
        else if([matches count] > 1) {
            NSLog(@"Error: More than one object for unique record");
            returnValue = YES;
    
        } else if ([matches count] == 0) {
            returnValue = NO;
        } else {
            returnValue = YES;
        }
    
        return returnValue;
    }
    
  • Alex Stone
    Alex Stone about 12 years
    Thanks Kevin, I'll test it out!
  • Matthias Bauch
    Matthias Bauch about 12 years
    a single equal sign is perfect for use in a NSPredicate.
  • Kevin Low
    Kevin Low about 12 years
    Oh! I guess you're right! Wow, it seems odd that would be the case (given that everywhere else in coding a single equal sign is an assignment).
  • chadbag
    chadbag over 10 years
    A single equal sign is assignment only in C like / C derived languages and ones that are inspired by them. Lots of languages (Algol derived for example [Pascal, Ada, Modula, Oberon] use the single = for equality