如何在Core Data中使用二进制标志?

23

我在Core Data数据库中有一个int32属性。 我将这个int用作enum的位字段。

是否可以创建一个NSPredicate,根据此int的二进制值查询项目?例如@"bitFieldAttribute & 0x0001"

我还想知道是否可以使用二进制类型的属性实现这一点?

4个回答

30

NSPredicate可以处理这个问题,但我不确定CoreData是否会接受它作为有效的谓词用于数据存储的执行。如果您使用SQLite后备存储,则可能会遇到将按位运算符转换为SQL查询的问题。您需要尝试一下。

然而,语法就像你预期的那样:

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

日志:

3 & 1 > 0
1

对于在二进制类型的属性上执行此操作(即定义为data的属性),这可能行不通。位运算符只有在操作整数时才真正有意义(就我所知),因此在NSData上执行它并没有多大意义。首先将其转换为数字,然后再尝试执行。

编辑

看起来SQLite支持此语法,因为位运算符自2001年以来就存在,这意味着Core Data也可能接受它。


太好了!!!非常感谢!我也非常怀疑CodeData是否能转换为SQL,但我刚刚测试了一下,似乎是可以的。 - CodeFlakes
通常情况下,检查(x & bits) != 0(x & bits) > 0更安全。原因是设置最高位可能会使数字变为负数。唯一的例外是当您完全确定该数字是无符号时。 - HughHughTeotl

10

rockfakie几乎是正确的,但是

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

这就是我所需要的。


嗯,我在使用CoreData时遇到了错误"'NSInvalidArgumentException',原因是:不支持的函数表达式 banned & 8",该表达式为 (banned & 8) == 0 - chadbag
请问您能否发布完整的NSPredicate定义? - Jim Holland
问题已经解决。这是因为一个愚蠢的笔误,属性名称由于一时糊涂而写错了(一直在处理应用程序用来填充其对象的mysql侧面,并使用了mysql列名而不是CD属性名)。谢谢。 - chadbag
这应该是使用“%i”正确语法的正确答案。 - Jingshao Chen

8

以下是这种技术的一个例子/应用。

假设您有一个NSManagedObject,它具有名为"typeValue"的整数属性。

在代码的某个地方定义一个按位枚举:

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

现在,如果要查询类型为 One 或 Three 但不是 Two 的托管对象,请执行以下操作:
SomeType valueOneOrThree = SomeTypeValueOne | SomeTypeValueThree;

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

// construct NSFetchRequest as normal with predicate...

-1

我很怀疑这个。

但是你可以使用一个枚举来存储属性中的值,并使用直接比较而不是位掩码。


我不明白你的意思。我的意图是获取与特定位值匹配的实体(不限于完全相同的位序列)。 - CodeFlakes
你能给出一个使用位掩码技术的例子吗? - Ciprian L.
@CiprianL。在这里:我有一堆实体,代表着生物(很多生物),还有一堆世界(大约16个),我需要将这些生物呈现出来。同样的生物可以在多个世界中呈现。所以现在,我需要获取应该在A、B和D世界中呈现的生物。 - igrek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接