10

I need to build an NSPredicate with many pieces of data. For example in SQL I would do something like the following:

SELECT * 
  FROM TRANSACTIONS
  WHERE CATEGORY IN (categoryList)
    AND LOCATION IN (locationList)
    AND TYPE IN (typeList)
    AND NOTE contains[cd] "some text"
    AND DATE >= fromDate
    AND DATE <+ toDate

I'm struggling with how to build this as an NSPredicate for use with Core Data. I've read the documentation... which only provides simplistic examples. If anybody can point me to a more complex example I would certainly appreciate it.


Well, I had an answer out here for two years that many people found helpful. My post was deleted. Here is the updated URL with the solution.

https://www.radeeccles.com/convert-sql-statement-to-an-nspredicate-for-use-with-core-data/

Bhavin Ramani
  • 3,221
  • 5
  • 30
  • 41
radesix
  • 5,834
  • 5
  • 24
  • 39
  • Did you try inputting your where clause in the predicate. It has a method to build one from string that is pretty powerful. – Eric Fortin Oct 17 '10 at 23:15
  • Im not aware of any place that lets me specify a SQL statement which generates a predicate. Please advise. – radesix Oct 18 '10 at 22:53
  • I don't know why my post keeps getting deleted. This article has helped MANY people http://www.radeeccles.com/convert-sql-statement-to-an-nspredicate-for-use-with-core-data/ – radesix Mar 13 '13 at 16:29

1 Answers1

9

What you need to do is to create a Predicate for each one of your clauses. For example let's break down your query:

  1. SELECT * FROM TRANSACTIONS
  2. WHERE CATEGORY IN (categoryList)
  3. AND LOCATION IN (locationList)
  4. AND TYPE IN (typeList)
  5. AND NOTE contains[cd] "some text"
  6. AND DATE >= fromDate AND DATE <+ toDate

Based on this, you have 5 predicates (2-6). So let's work on them one by one.

 NSPredicate *inCategoryPredicate = [NSPredicate predicateWithFormat:@"Category IN %@", categoryList];

 NSPredicate *locationPredicate = [NSPredicate predicateWithFormat:@"Location IN %@", locationList];

 NSPredicate *typePredicate = [NSPredicate predicateWithFormat:@"Type IN %@", typeList];

 NSPredicate *notePredicate = [NSPredicate predicateWithFormat:@"Note contains[c] %@", @"Some Text"];

 NSPredicate *startDatePredicate = [NSPredicate predicateWithFormat:@"Date => @", fromDate];

 NSPredicate *endDatePredicate = [NSPredicate predicateWithFormat:@"Date <= @", toDate];

Now you just need to join them into just one predicate: Apple's documentation states:

You should structure compound predicates to minimize the amount of work done. Regular expression matching in particular is an expensive operation. In a compound predicate, you should therefore perform simple tests before a regular expression;

This being said then you should start with the "easy" predicates first. So:

NSCompoundPredicate *compoundPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects: startDatePredicate, endDatePredicate, inCategoryPredicate, locationPredicate, typePredicate, notePredicate];

You can always get an idea of what the predicate (sql where) looks like if you NSLog it.

Ares
  • 5,905
  • 3
  • 35
  • 51
  • Is it possible to answer [this question](https://stackoverflow.com/questions/46388393/create-complicated-nscompoundpredicate-in-swift-3) please? – Amir Shabani Sep 24 '17 at 09:46