IOS/Objective-C: Out of Range Error with NSPredicate - ios

I have built an NSPredicate similar to that below before and it worked perfectly. However, this time, it is generating the error:
'NSRangeException', reason: '-[NSTaggedPointerString characterAtIndex:]: Index 1 out of bounds; string length 1'
Here is how I build the predicate:
NSString *shortTitleClause = nil;
NSString *longTitleClause = nil;
Edit:
Adding clauses:
shortTitleClause =[NSString stringWithFormat:#"(shorttitle contains[c] %#)", searchText];
longTitleClause =[NSString stringWithFormat:#"(longtitle contains[c] %#)", searchText];
//My actual predicate has many more clauses but am getting same error no matter how many.
NSMutableArray *predArr = [#[] mutableCopy];
if (shortTitleClause.length > 0){
[predArr addObject:shortTitleClause];
}
if (longTitleClause.length > 0){
[predArr addObject:longTitleClause];
}
NSString *predStr = [predArr componentsJoinedByString:#"||"];
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:predStr];
searchResults = [theBooks filteredArrayUsingPredicate:resultPredicate];
When searching for the letter 'S' the predicate logs as: `(shorttitle contains[c] S)||(longtitle contains[c] S)`
It is not clear to me what the taggedPointerString refers to me. Can anyone see why I am getting this error?

You cannot use stringWithFormat to replace %# values when preparing predicates. Use predicateWithFormat instead. And don't join them using componentsJoinedByString - use NSCompoundPredicate to combine multiple predicates:
shortTitlePredicate = [NSPredicate predicateWithFormat:#"(shorttitle contains[c] %#)", searchText];
longTitlePredicate = [NSPredicate predicateWithFormat:#"(longtitle contains[c] %#)", searchText];
NSPredicate *resultPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:#[shortTitlePredicate,longTitlePredicate]];

Related

Obj-C - NSPredicate - Can I implement an 'or IF' statement?

I'm trying to write a filter with NSPredicate that states:
IF field_Uid contains 47 and field_Target contains 202...display these items
This portion works great. However, I also want to show items in which the reverse is true, eg.:
OR IF fieldUid contains 202 and fieldTarget contains 47...display these
items also
Right now, I have the following code:
NSString *targetedUser = #"47";
NSString *myID = #"202";
NSPredicate *p1 = [NSPredicate predicateWithFormat:#"fieldUid contains[cd] %#", targetedUser];
NSPredicate *p2 = [NSPredicate predicateWithFormat:#"fieldTarget contains[cd] %#", myID];
//E.G. See p3 & p4 being the reverse?
// NSPredicate *p3 = [NSPredicate predicateWithFormat:#"fieldUid contains[cd] %#", myID];
// NSPredicate *p4 = [NSPredicate predicateWithFormat:#"fieldTarget contains[cd] %#", targetedUser];
NSCompoundPredicate *p = [NSCompoundPredicate andPredicateWithSubpredicates:#[p1, p2/*, p3, p4*/]];
NSArray *filtered = [self.messages filteredArrayUsingPredicate:p];
How would I write in the latter? I'm not sure how to do it without making the statement requiring all 4 lines to be true? (See commented out code - I've left it in so you can see what I mean...)
Just combine two compound "and" predicates using a compound "or" predicate.
You have the first compound "and" predicate in your question. Create the 2nd compound "and" predicate as needed.
Now use [NSCompoundPredicate orPredicateWithSubpredicates:] passing in the two "and" compound predicates.
you can also use
NSString *targetedUser = #"47";
NSString *myID = #"202";
//this will easily fix your issue, simply update your query like this
NSPredicate *p = [NSPredicate predicateWithFormat:#"(fieldUid contains[cd] %# AND fieldTarget contains[cd] %#) OR (fieldUid contains[cd] %# AND fieldTarget contains[cd] %#)", targetedUser, myID, myID, targetedUser];
NSArray *filtered = [self.messages filteredArrayUsingPredicate:p];

How to concatenate two fields for search with NSPredicate?

For example, I have object like #{#"firstName":#"aaa", #"lastName":#"bbb"}.
Now I'm trying to search with next predicate:
NSPredicate *predicateFirstName = [NSPredicate predicateWithFormat:#"firstName contains [c] %#", searchString];
NSPredicate *predicateLastName = [NSPredicate predicateWithFormat:#"lastName contains [c] %#", searchString];
NSPredicate *orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:#[predicateFirstName, predicateLastName]];
searchUsersArray = [usersArray filteredArrayUsingPredicate:orPredicate];
I need a predicate, which will be return for search string #"aa bb" users whose first name ENDED with "aa" and lastName BEGINS with #"bb"
NSPredicate *predicateLastName = [NSPredicate predicateWithFormat:#"(firstName AND lastName contains [c] %#)", searchString]
don't work for me.
First divide the search string in the end-part and the begin-part:
NSArray *parts = [#"aa bb" componentsSeperatedByString:#" "];
Then use BEGINSWITH and ENDSWITH:
[NSPredicate predicateWithFormat:#"(firstName ENDSWITH[c] %#) AND (lastName BEGINSWITH[c] %#", parts[0], parts[1]];
Alternatively you can add a computed property to the entity concatinating the first name and last name and then search in this property.
Try like this hope it help you
NSString *matchString = [NSString stringWithFormat: #"(.*aa|bb.*)",searchText];
NSString *predicateString = #"keyword MATCHES[c] %#";
NSPredicate *predicate =[NSPredicate predicateWithFormat: predicateString, matchString];
Thanks
Use keyword BEGINSWITH instead of contains.
NSPredicate *predicateFirstName = [NSPredicate predicateWithFormat:#"firstName BEGINSWITH [c] %#", searchString];
NSPredicate *predicateLastName = [NSPredicate predicateWithFormat:#"lastName BEGINSWITH [c] %#", searchString];

NSPredicate for filtering array with ( ' ) character issue

Here is my test for filtering the array by a string. It work well if my string doesn't contain (') character
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
//NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"]; -> it work
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b''"]; -> it crash
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
I also try to change my string to 'b\'' or 'b''' but it still crash
Here is the crash log
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unable to parse the format string "SELF contains[c] 'b'''"'
How to resolve it? Any help would be great appreciated.
Please try to filter result as follows:
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
NSString *strToBeSearched = #"b'";
//NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b'"]; -> it work
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",strToBeSearched]; //-> it also work
//OR
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b\\''"];
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"containB = %#",beginWithB);
try this
NSString *searchword = #"b";
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] %#",searchword];
you get output of
You were pretty close when you tried backslash. This is the character that NSPredicate uses to escape special characters. However, you need two, not one, backslash:
NSMutableArray *array = [NSMutableArray arrayWithObjects:#"Nick", #"b'en", #"Adam", #"Melissa", #"arbind", nil];
NSPredicate *sPredicate = [NSPredicate predicateWithFormat:#"SELF contains[c] 'b\\''"];
// ^^
NSArray *beginWithB = [array filteredArrayUsingPredicate:sPredicate];
NSLog(#"beginwithB = %#",beginWithB);
The reason you need two is Objective-C compiler. It processes all string literals in your code, and replaces escape sequences it encounters. If you would like NSPredicate to see a single backslash, your string literal needs to have two backslashes, because backslash itself is encoded as \\ in Objective-C string literals.
If your name is b'en then,
NSString *name = #"b'en";
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name == \"%#\"", name];
Hope this will help :)

Compound Predicate doesn't work

I have an array of objects with name and address.
Both properties are of type NSString.
But when i'm using the compound predicate with both results i don't get any result. If i'm using just one predicate it works very well.
Has anyone an idea whats going wrong here in my code? thnx
-(void)filterContentForSearchString:(NSString*) searchText
{
NSPredicate *resultsPredicate = [NSPredicate predicateWithFormat:#"SELF.name like[cd] %#", searchText];
NSPredicate *resultsPredicate2 = [NSPredicate predicateWithFormat:#"SELF.place like[cd] %#", searchText];
NSPredicate *compoundpred = [NSCompoundPredicate andPredicateWithSubpredicates:#[resultsPredicate, resultsPredicate2]];
self.searchResults = [self.companies filteredArrayUsingPredicate:compoundpred];
}
Can you try using a single predicate declaration
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"SELF.name like[cd] %# OR SELF.place like[cd] %#", searchText, searchText];
and filter the array with it directly
self.searchResults = [self.companies filteredArrayUsingPredicate:predicate];

NSPredicate multiple conditions no results

i'm using a NSPredicate to filter an array in my searchbar. This is my code which works perfectly.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.name contains[cd] %#",searchText];
filteredArray = [NSMutableArray arrayWithArray:[storesArray filteredArrayUsingPredicate:predicate]];
The problem is i want to add a second condition as the name which is the address. How can i do this? I've tried this, but then none of the predicates are working.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.name contains[cd] %#",searchText];
NSPredicate *predicate1 = [NSPredicate predicateWithFormat:#"SELF.address contains[cd] %#",searchText];
NSPredicate *fullPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:#[predicate, predicate1]];
filteredArray = [NSMutableArray arrayWithArray:[storesArray filteredArrayUsingPredicate:fullPredicate]];
You can use the OR comparison operator:
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"SELF.name contains[cd] %# OR SELF.address contains[cd] %#", searchText, searchText];

Resources