Core Data NSPredicate检查BOOL值

42

我目前遇到了一个问题,就是无法从数据库中检索所有符合条件(即一个参数为TRUE)的数据。

我正在使用NSPredicate,以下是示例代码:

NSManagedObjectContext *context = managedObjectContext_;

if (!context) {
    // Handle the error.
    NSLog(@"ERROR CONTEXT IS NIL");
}

NSEntityDescription *entity = [NSEntityDescription entityForName:@"tblcontent" inManagedObjectContext:managedObjectContext_];

NSFetchRequest *request = [[NSFetchRequest alloc] init];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"bookmarked == YES"];

[request setPredicate:predicate];
我尝试了几乎所有的谓词格式,但它仍然无法获取值为YES的书签。我甚至尝试过 (@"bookmarked == %d",YES),但没有成功。我不想通过执行if(object.bookmarked == YES)手动筛选整个数组..blabla的方式来获取整个数组并手动筛选。我真的很感激您的帮助。非常感谢。
9个回答

71

根据苹果文档这里,我们可以使用以下两种方法来比较布尔值:

NSPredicate *newPredicate = [NSPredicate predicateWithFormat:@"anAttribute == %@",[NSNumber numberWithBool:aBool]];
NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"anAttribute == YES"];

然而,以上谓词不能筛选出空的anAttribute。要处理空属性,按照苹果文档这里所述,需要使用以下方法:

predicate = [NSPredicate predicateWithFormat:@"firstName = nil"]; // it's in the document
或者
predicate = [NSPredicate predicateWithFormat:@"firstName == nil"]; // == and = are interchangeable here

30

悄悄地走进来,给出Swift 3/4的答案:

let predicate = NSPredicate(format: "boolAttribute == %@", NSNumber(value: true))

显然,由于 Apple 不接受字面意义的布尔值,我们必须使用 NSNumber。

从这里偷来的 ;)


哎呀!你救了我的命...为什么它用 false 可以工作,但是用 true 就不行了...我花了很长时间才找到导致我的应用程序崩溃的那一行代码,因为堆栈跟踪根本没有帮助。 - randomcontrol

13

因某些原因,Flow的解决方案对我不起作用:

NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"anAttribute == YES"];

然而,这确实做到了:

NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"anAttribute == 1"];

1
对于我的情况,Flow的解决方案也不起作用。只有当anAttribute == 1时才有效。 - Hussain KMR Behestee

10

我来晚了,但如讨论所述,使用0和1是正确的方式,不过有一种更好的方法可以使用NSNumber BOOL字面量,例如@YES或@NO,它将其转换为1或0,但更加视觉友好。

NSPredicate *testForTrue = [NSPredicate predicateWithFormat:@"anAttribute == %@", @NO];

5

Core Data实体在创建属性时没有任何默认值,因此为了使您的谓词起作用,您应该为布尔属性设置默认值或以这种方式使用谓词。

如果您为实体的任何布尔属性提供默认值(NO或YES),则应该像这样使用谓词

[NSPredicate predicateWithFormat:@"boolAttribute == %@", @NO];
[NSPredicate predicateWithFormat:@"boolAttribute == NO", @NO];
[NSPredicate predicateWithFormat:@"boolAttribute == %0"];

如果您没有默认值或某些实体已经创建而没有默认值,那么要通过false值进行过滤,请使用以下语句:

[NSPredicate predicateWithFormat:@"boolAttribute == %@ || boolAttribute == nil", @NO];

空值检查很重要,特别是在获取完成后,布尔条目可能会显示为 false,而实际上它们是 null。 - lewis

2

Swift:

fetchRequest.predicate = NSPredicate(format: "%K == NO",#keyPath(MyEntity.isOccupied))

或者

fetchRequest.predicate = NSPredicate(format: "%K == NO",\MyEntity.isOccupied)

1
你没有提到你得到了什么结果。你的代码清单中缺少两件事情,一是你设置请求实体的地方,二是你实际上要求上下文执行获取请求的地方。我建议从这里开始。

嗨,我在代码中没有包含那个。我得到的结果基本上是全部的。就好像没有任何过滤起作用一样。 - user281300
再次您好,我认为之前有些问题。即每个返回的内容都具有object.bookmarked = YES,尽管我已将其默认设置为NO。我需要检查一下。我想谓词是有效的。无论如何,谢谢。 - user281300
2
哈哈,现在它运行得很好。我这个笨蛋忘记先从模拟器中重置数据库了,真是太糊涂了!无论如何,上面的代码没问题。 - user281300

1
对我来说,这是因为在保存时分配对象值错误造成的。
你必须像这样保存。
YourNSMNanagedObject.visibleBoolean = [[NSNumber alloc] initWithBool:false]

然后在获取时所有谓词都会起作用。
例如:
// Filter only unvisible item
NSPredicate *favouriteFilter = [NSPredicate predicateWithFormat:@"visibleBoolean==NO"];

0

我一直被这个问题困扰,而且并不总是清楚地知道核心数据中的布尔值会保存为NSNumbers。

大多数情况下,当创建实体时,我会确保为任何布尔属性设置@NO,但总有这样的情况,我花费了很多时间试图弄清楚为什么测试未通过,而我忘记在实体创建时设置@NO。

这可能不是清晰代码的最佳选择,但我现在已经开始始终在核心数据中使用!=谓词来表示布尔值,例如(isCompleted != YES),而不是(isCompleted == NO)。事实上,nil == false模式在其他所有地方都是正确的,但在核心数据谓词和属性中却不是,这可能非常令人困惑。


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