Search code examples
objective-ccore-datanspredicatensfetchrequest

executeFetchRequest crashes app for NSPredicate with NSString object on left side of CONTAINS


I am trying to fetch objects from Core Data whose 'name' attribute CONTAINS a specific NSString sPersonName. Following code is doing that

NSString *sPersonName = @"Some Value";
NSFetchRequest<Entity*>* request = [Entity fetchRequest];
[request setPredicate:[NSPredicate predicateWithFormat:@"name CONTAINS[c] %@", sPersonName]];
NSError *error;
NSArray *arrResults = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];

this code executes fine and I am getting results as expected.

But if I don't get any results from the upper request, I try to get objects from Core Data such that sPersonName string CONTAINS value of 'name' attribute of saved objects. Below is the code for that.

request = [Entity fetchRequest];
[request setPredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS[c] name", sPersonName]];
arrResults = [self.persistentContainer.viewContext executeFetchRequest:request error:&error];

This command fails and crashes the app creating following error

-[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x170a43750
2017-01-24 23:02:28.124224 TestApp[2934:845977] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x170a43750'

Can anyone guide me what am I doing wrong ? Thanks a lot.

EDIT screenshot of predicate


Solution

  • So, after few days of trial and error, I found the solution. NSPredicate expects a data structure object such as NSArray to be on the left side for CONTAINS. Passing a NSString object breaks it.

    So, the solution was to covert NSString into NSArray. Below code runs fine.

    NSArray *arrName = [sPersonName componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ CONTAINS[c] name", arrName];
    
    
    [request setPredicate:predicate];
    arrResults = [self.m_persistentContainer.viewContext executeFetchRequest:request error:&error];