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:错误:严重的应用程序错误。抓住了例外 在核心数据更改处理期间。这通常是一个bug NSManagedObjectContextObjectsDidChangeNotification的观察者。 具有GROUP BY组件的查询中的SELECT子句只能包含 在GROUP BY或聚合函数中命名的属性
我应该在分组中使用propertiesToFetch
中的所有字段。但我不想这样做......
答案 0 :(得分:3)
一种选择是使用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将尽力优化内存和速度,但如果你有大量的话,你应该小心。