Swift NSFetchRequest 按一个属性分组
Posted
技术标签:
【中文标题】Swift NSFetchRequest 按一个属性分组【英文标题】:Swift NSFetchRequest group by one attribute 【发布时间】:2015-11-13 18:26:59 【问题描述】: let fetchRequest = NSFetchRequest(entityName: "Product")
fetchRequest.predicate = NSPredicate(format: "shopItem.wishList == %@", currentWishList)
fetchRequest.resultType = .DictionaryResultType
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "mainBestPrice", ascending: true)]
let minPriceExpression = NSExpression(format: "min:(mainBestPrice)")
let minPriceED = NSExpressionDescription()
minPriceED.expression = minPriceExpression
minPriceED.name = "productPrice"
minPriceED.expressionResultType = .DoubleAttributeType
fetchRequest.propertiesToFetch = ["shopItem.keyword", "productTitle", minPriceED]
fetchRequest.propertiesToGroupBy = ["shopItem.keyword"]
我想用NSFetchRequest
按一个字段分组,但总是报错:
CoreData:错误:严重的应用程序错误。异常被捕获 在核心数据更改处理期间。这通常是一个错误 NSManagedObjectContextObjectsDidChangeNotification 的观察者。 带有 GROUP BY 组件的查询中的 SELECT 子句只能包含 在 GROUP BY 或聚合函数中命名的属性
我应该在分组中使用来自propertiesToFetch
的所有字段。但我不想这样做......
【问题讨论】:
没有办法解决这个问题。您必须将productTitle
添加到propertiesToGroupBy
,或者将其从propertiesToFetch
中删除。可能你可以通过不同的方式获得你想要的东西:要么使用键值编码集合运算符,要么使用 NSFetchedResultsController。如果您编辑帖子以包含实体和关系的详细信息(一对多、多对多),我相信您会得到一些建议。
我真的需要所有字段,你能告诉我如何在fetchRequest
之后对结果进行分组吗?
【参考方案1】:
一种选择是使用NSFetchedResultsController
(请参阅Apple Docs)。这通常用于填充表视图,但也可用于对 CoreData 提取的结果进行分组 - sectionNameKeyPath
确定分组。必须以确保组中的所有项目一起排序的方式对提取进行排序。在您的示例中,您按shopItem.keyword
分组,因此您需要将shopItem.keyword
指定为第一个排序描述符。第二个排序描述符应该是mainBestPrice
(升序),因此每个组中的第一个项目是该组中mainBestPrice
最低的项目。因此,FRC 的配置如下所示:
let fetchRequest = NSFetchRequest(entityName: "Product")
fetchRequest.predicate = NSPredicate(format: "shopItem.wishList == %@", currentWishList)
let keyWordSort = NSSortDescriptor(key: "shopItem.keyword", ascending: true)
let priceSort = NSSortDescriptor(key: "mainBestPrice", ascending: true)
fetchRequest.sortDescriptors = [keyWordSort, priceSort];
let myFetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: self.managedObjectContext!, sectionNameKeyPath:"shopItem.keyword", cacheName:nil)
do
try myFetchedResultsController.performFetch()
catch let error as NSError
// Replace this implementation with code to handle the error appropriately.
print("Unresolved error \(error), \(error!.userInfo)")
abort()
现在,最低最优价格的产品将成为每个部分的第一项,例如。对于第一部分(即第一个shopItem.keyword
):
let firstProduct = myFetchedResultsController.sections![0].objects![0] as! Product
或获取它们的数组(对于所有shopItem.keyword
s),
let products = myFetchedResultsController.sections!.map() $0.objects![0] as! Product
NSFetchedResultsController 将尽最大努力优化内存和速度,但如果你有大容量,你应该小心。
【讨论】:
以上是关于Swift NSFetchRequest 按一个属性分组的主要内容,如果未能解决你的问题,请参考以下文章
Swift 3 - NSFetchRequest 不同的结果
Swift 3. NSFetchRequest propertiesToFetch
NSFetchRequest 上的 Swift2.0 CoreData 问题