23

I have an int32 attribute in a Core Data database. I use this int as an enum bit field.

Is it possible to create a NSPredicate to query items based on the binary value of this int ? Something like @"bitFieldAttribute & 0x0001"?

I'm also wondering if this is possible with a binary typed attribute ?

Shmidt
  • 16,436
  • 18
  • 88
  • 136
CodeFlakes
  • 3,671
  • 3
  • 25
  • 28

4 Answers4

30

NSPredicate can handle it, but I'm not sure if CoreData will accept it as a valid predicate for execution on a data store. It might have trouble converting the bitwise operator into a SQL query (if you're using a SQLite backing store). You'll just have to try it.

The syntax, however, is just what you'd expect:

NSPredicate * p = [NSPredicate predicateWithFormat:@"(3 & 1) > 0"];
NSLog(@"%@", p);
NSLog(@"%d", [p evaluateWithObject:nil]);

Logs:

3 & 1 > 0
1

As for doing this on a binary-typed attribute (ie, one defined as data, right?) This probably won't work. Bitwise operators only really make sense when operating on integers (insofar as I understand them), so executing it on an NSData wouldn't make much sense. Convert it to a number first, and then it might work.

edit

It would appear that SQLite supports this syntax, since bitwise operators have been around since 2001, which means that Core Data will probably accept it as well.

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • That works !!!! Thanks a lot ! I was very dubious too that CodeData would translate to SQL but I've just tested it and it seems to work. – CodeFlakes Jan 17 '11 at 20:23
  • Almost always safer to check `(x & bits) != 0` rather than `(x & bits) > 0`. The reason being that setting the highest bit can turn the number negative. Only exception is when you're completely certain the number is unsigned. – HughHughTeotl Feb 11 '16 at 10:53
10

rockfakie is so nearly right but

NSPredicate *someTypePredicate = [NSPredicate predicateWithFormat:@"(typeValue & %i) == %i", valueOneOrThree,valueOneOrThree];

Is what I needed.

Jim Holland
  • 1,180
  • 12
  • 19
  • Hnmm, I am getting CoreData barfing with the error "'NSInvalidArgumentException', reason: 'Unsupported function expression banned & 8" with the expression `(banned & 8) == 0` – chadbag Dec 08 '14 at 20:19
  • Can you post your whole NSPredicate definition, please? – Jim Holland Dec 11 '14 at 14:35
  • been fixed. Was a stupid typo of the property name due to a brain fart (had been dealing with the mysql side that the app uses to populate its objects and used the mysql column name instead of the CD property name). Thanks. – chadbag Dec 11 '14 at 19:59
  • This should be the correct answer for the right syntax use of `%i` – Jingshao Chen Oct 10 '15 at 20:55
8

Here is one example / application of this technique.

Say you have a NSManagedObject that has an integer attribute with the keypath "typeValue".

Somewhere in your code define a bitwise enumeration:

typedef enum SomeType {
    SomeTypeValueOne = 0x1,
    SomeTypeValueTwo = 0x2,
    SomeTypeValueThree = 0x4
} SomeType;

Now to query for managed objects that are of type say One or Three but not Two, do the following:

SomeType valueOneOrThree = SomeTypeValueOne | SomeTypeValueThree;

NSPredicate *someTypePredicate = [NSPredicate predicateWithFormat:@"(typeValue & %i) == typeValue", valueOneOrThree];

// construct NSFetchRequest as normal with predicate...
rockfakie
  • 2,330
  • 3
  • 17
  • 9
-1

I hardly doubt it.

But you may use an enum for the values stored in the attribute, and use a direct comparison instead of a bit masking.

Ciprian L.
  • 587
  • 2
  • 7
  • I don't get what you mean. What I want to do is to fetch entities that match certain bit values (not limited to the exact same bit sequence). – CodeFlakes Jan 17 '11 at 19:09
  • Can you provide an example as for why you need the bit masking technique? – Ciprian L. Jan 17 '11 at 19:13
  • @CiprianL. here it is: i have a bunch of entities, representing creatures(lots of creatures), and i have a bunch of worlds(like 16 or so), where i should present those creatures into. Same creatures can be presented in multiple worlds. So now, i need to fetch creatures that should be presented in worlds `A`, `B` and `D` – igrek Sep 07 '17 at 09:49