25

Hello Need help with predicate. The problem is that I want to have one function which will fetch from database depends on the multiple values it receives, but the values don't always exist, does it mean I have to create several different predicates?

Code below

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"brand_id LIKE %@ AND brand_id LIKE %@ AND brand_id LIKE %@ AND brand_id LIKE %@ AND brand_id LIKE %@ AND item_category LIKE %@ AND item_make LIKE %@ AND item_gender LIKE %@ || item_price>%@ || item_price<%@",
                              brand_one, brand_two, brand_three, brand_four, brand_five, categoryString, makeString, genderString,[NSNumber numberWithInt:price_bottom],[NSNumber numberWithInt:price_top]];

brand_one, brand_two and etc sometimes exist and sometimes don't.

And how should it for item_gender for example. Let's if there is no gender specified than to have both of them.

Sorry if my description of the problem confusing.

Base on Gobras comments the following code was produces

NSArray *brands = [NSArray arrayWithObjects:brand_one, brand_two, brand_three, brand_four, brand_five, nil];

    NSPredicate *predicate_brands = [NSPredicate predicateWithFormat:@"brand_id like %@" argumentArray:brands];

Logical explanation of what what search function should

  1. fetchrequest
  2. predicate on fetch request

predicate based on 5 brand ids, item id, item category, item make, item gender, if any of above is empty it should fetch all related entries for example if item category is empty it should fetch all "Jewellery, Watches and etc" but limit it with the rest of the predicate expressions.

Should I create for example compound predicates for brands and than create another one for item category with values "item_category like Jewellery" and "item_category like Watches" and after that how do I exactly bring them together?

Rouslan Karimov
  • 585
  • 2
  • 7
  • 19

3 Answers3

61

Assemble an appropriate collection of individual predicates into NSCompoundPredicate

as in

NSMutableArray *parr = [NSMutableArray array];
if([brand_one length]) { 
    [parr addObject:[NSPredicate predicateWithFormat:@"brand_id LIKE %@",myBrandId]];
}
if([brand_two length]) { 
     // etc 
}

NSPredicate *compoundpred = [NSCompoundPredicate andPredicateWithSubpredicates:parr];

You can stack up your predicates with orPredicateWithSubpredicates: and andPredicateWithSubpredicates: and NSCompoundPredicate being a NSPredicate itself can be compounded.

See https://developer.apple.com/documentation/foundation/nscompoundpredicate

Cœur
  • 37,241
  • 25
  • 195
  • 267
Warren Burton
  • 17,451
  • 3
  • 53
  • 73
  • thanx Warren, I still can't get it right in my head, I think it is just over my level of understanding. I run few tests and it seems that I'm having the logical issues now... Will really appreciate if you can help me... I have added the logical explanation of what I want to do... – Rouslan Karimov Jun 08 '11 at 17:18
  • and how I actually use the compound predicate? cpred value where do I use, is it in [NSPredicate predicateWithFormat] ? – Rouslan Karimov Jun 08 '11 at 17:39
  • Same place as you would have used the original one. You are doing the same in code as you are doing with your format string. A NSCompoundPredicate is a NSPredicate – Warren Burton Jun 08 '11 at 18:47
4

For those who are interested in Swift!

let arrPred = [NSPredicate(format: "yourAttribute LIKE %@", toCompareID), NSPredicate(format: "yourAttribute2 LIKE %@", toCompareID2)] //Add as many predicates you want in short make your query

let compoundpred:NSPredicate = NSCompoundPredicate(andPredicateWithSubpredicates: arrPred)
var arrFiltered = yourArray.filteredArrayUsingPredicate(compoundpred)
Rein rPavi
  • 3,368
  • 4
  • 22
  • 32
1

It's pretty simple to build the predicate dynamically: combine your predicate format string with desired number of conditions and build corresponding NSMutableArray with the arguments. [NSPredicate predicateWithFormat:argumentArray:] will do the rest.

Gobra
  • 4,263
  • 2
  • 15
  • 20
  • Thanx I have tried this but it doesn't fetch the right thing. I have added the code above in the question based on your comments is that how it should look like? Still doesn't fetch multiple brands for me. – Rouslan Karimov Jun 08 '11 at 11:38
  • In the updated code you have only one condition while there should one condition per each valid brand_. @Warren Burton suggested almost the same approach with a bit more complicated (but yet maybe more proper) way to build the complex NSPredicate dynamically. – Gobra Jun 08 '11 at 16:30