NSFetchRequest和predicateWithBlock

Bil*_*hed 26 core-data objective-c nsfetchedresultscontroller nsfetchrequest

我正在使用一个使用Core Data和NSManagedObjects来填充UITableView的应用程序.我的应用程序中只有一个类叫做Event.我已经创建了以下自定义实例方法Event:

- (BOOL)isExpired {
    return ([[self.endOn dateAtEndOfDay] timeIntervalSinceNow] < 0);
}
Run Code Online (Sandbox Code Playgroud)

我想将UITableView显示Event对象的内容限制为仅过期的事件 - 即isExpired返回的事件YES.我试图通过添加NSPredicateNSFetchRequest:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary * bindings) {return([evaluatedObject isExpired]);}];
[fetchRequest setPredicate:predicate];
Run Code Online (Sandbox Code Playgroud)

但是我得到了错误:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Problem with subpredicate BLOCKPREDICATE(0x272ac)' ***.这是否意味着您不能将块谓词与NSFetchRequest一起使用?或者我刚构建它不正确?

谢谢!

ig2*_*g2r 24

因此,似乎我们在原始帖子的评论中已经确定这可能是由SQLite存储与块谓词不兼容引起的,因为Core Data无法将这些转换为SQL以在商店中运行它们(感谢JoostK).

可能有几种方法可以克服这个问题:

  • 如果实体的结束日期是常规属性,则可以将过期约束表示为谓词格式字符串而不是块谓词,Core Data应该能够将其转换为SQL子句.
  • 如果可以实现上述目的,您可能更愿意使用获取请求模板来检索过期的项目.但是,您需要传入替换变量$NOW,以便访问当前日期.这样做的好处是可以在模型编辑器中显示谓词模板.
  • 但是,这两种方法都存在重复现有功能(即您的isExpired方法)的缺点.因此,另一种方法是首先获取所有合格实体而不管其到期状态,然后对生成的实体集执行专用过滤步骤以清除未过期的实体.从那时起,它们已经完全从商店中复活,你应该可以使用块谓词.


Vic*_*cas 7

您可以在不指定谓词的情况下执行常规获取请求,然后过滤生成的数组:

NSArray *allEvents = [context executeFetchRequest:fetchRequest];

if (!allEvents) { // do error handling here
}

NSArray *expiredEvents = [allEvents filteredArrayUsingPredicate:predicate];
Run Code Online (Sandbox Code Playgroud)

  • 但我们不能将这两步技术与NSFetchedResultsController一起使用,对吧? (2认同)