Swift NSFetchRequest组由一个属性组成

时间:2015-11-13 18:27:00

标签: ios swift core-data

    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中的所有字段。但我不想这样做......

1 个答案:

答案 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将尽力优化内存和速度,但如果你有大量的话,你应该小心。