具有多个语句的 NSPredicate

Posted

技术标签:

【中文标题】具有多个语句的 NSPredicate【英文标题】:NSPredicate with multiple statements 【发布时间】:2013-04-13 07:45:14 【问题描述】:

我有带有四个语句/参数的NSPredicate。似乎所有这些都没有“包含”。它看起来像这样:

predicate = [NSPredicate predicateWithFormat:@"user.youFollow = 1 || user.userId = %@ && user.youMuted = 0 && postId >= %d", [AppController sharedAppController].currentUser.userId, self.currentMinId.integerValue];

似乎最后一部分:&& postId >= %d,被忽略了。如果我尝试:

predicate = [NSPredicate predicateWithFormat:@"user.youFollow = 1 || user.userId = %@ && user.youMuted = 0 && postId = 0", [AppController sharedAppController].currentUser.userId, self.currentMinId.integerValue];

我得到相同的结果(应该是 0)。我想知道这样的谓词应该是什么样子?

【问题讨论】:

你用括号试过了吗?就是看看是不是优先级的问题…… 我试过了:(user.youFollow = 1 || user.userId = %@) && (user.youMuted = 0 && postId >= %d). NSLog(@"%@", [predicate description]); 打印什么? 您可以尝试删除谓词的一些“片段”(简化它),看看结果是否符合您的预期...... 当一个逻辑条件中存在 OR 和 AND 运算时,必须使用括号。此外,使用== 而不是= 进行比较。尝试使用ORAND 而不是||&&。如果要比较两个字符串,请使用' 符号:user.userId == '%@' 【参考方案1】:

正如讨论中发现的那样,真正的问题是谓词用于 获取的结果控制器,并且谓词中使用的变量随时间而变化。

在这种情况下,您必须重新创建谓词和获取请求。这是记录在案的 在NSFetchedResultsController Class Reference 中的“修改获取请求”中。

所以在你的情况下,如果 self.currentMinId 发生变化,你应该

// create a new predicate with the updated variables:
NSPredicate *predicate = [NSPredicate predicateWithFormat:...]
// create a new fetch request:
NSFetchRequest *fetchRequest = ...
[fetchRequest setPredicate:predicate];

// Delete the section cache if you use one (better don't use one!)
[self.fetchedResultsController deleteCacheWithName:...];

// Assign the new fetch request and re-fetch the data:
self.fetchedResultsController.fetchRequest = fetchRequest;
[self.fetchedResultsController performFetch:&error];

// Reload the table view:
[self.tableView reloadData];

【讨论】:

谢谢,开始工作了!小注意,setFetchRequest 是只读的。我做到了:self.fetchedResultsController.fetchRequest setPredicate.... @Anders:感谢您的反馈! self.fetchedResultsController.fetchRequest setPredicate:newPredicate] 也可能有效,也许您想尝试一下。在这种情况下,您只需要一个新的谓词,而不是一个新的 fetch 请求。【参考方案2】:

你能试试下面的代码吗?

NSPredicate *youFollowPred = [NSPredicate predicateWithFormat:@"user.youFollow == 1"];
NSPredicate *userIdPred = [NSPredicate predicateWithFormat:@"user.userId == %@",[AppController sharedAppController].currentUser.userId];
NSPredicate *youMutedPred = [NSPredicate predicateWithFormat:@"user.youMuted == 0"];
NSPredicate *postIdPred = [NSPredicate predicateWithFormat:@"postId >= %d", self.currentMinId.integerValue];

NSPredicate *orPred = [NSCompoundPredicate orPredicateWithSubpredicates:[NSArray arrayWithObjects:youFollowPred,userIdPred, nil]];

NSPredicate *andPred = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:youMutedPred,postIdPred, nil]];

NSPredicate *finalPred = [NSCompoundPredicate andPredicateWithSubpredicates:[NSArray arrayWithObjects:orPred,andPred, nil]];

【讨论】:

谢谢,它有效。你知道 - NSPredicate *postIdPred = [NSPredicate predicateWithFormat:@"postId >= %d", self.currentMinId.integerValue]; - can have a dynamic %d` 变量。在进行新的提取之前需要更新我的谓词。 @sunilz:请注意,您的代码完全等同于谓词"(user.youFollow = 1 || user.userId = %@) && (user.youMuted = 0 && postId >= %d)", ...

以上是关于具有多个语句的 NSPredicate的主要内容,如果未能解决你的问题,请参考以下文章

为啥在具有相同变量的语句中使用多个等号?

SQL Server 更新语句基于具有多个值的 Select 语句

多个 INSERT 语句与具有多个 VALUES 的单个 INSERT

多个 INSERT 语句与具有多个 VALUES 的单个 INSERT

每个 'when' 块中具有多个值的 case 语句

具有多个条件的 if 语句