【问题标题】:Set NSSortDescriptor for CoreData using a calculated field使用计算字段为 CoreData 设置 NSSortDescriptor
【发布时间】:2020-04-01 15:28:25
【问题描述】:

我已使用扩展将计算属性添加到 CoreData 数据库。我想使用 NSSortDescriptor 和 FetchRequest 来根据这些计算属性之一过滤和排序 CoreData 信息。代码编译没有问题,并且在基于本机 CoreData 属性排序时工作正常,但在尝试基于计算字段应用 NSSortDescriptor 时代码在执行期间崩溃。

以下是从我的“GameLog+CoreDataProperties.swift”文件中提取的简化代码 sn-p,其中计算属性在扩展中定义。这可以正确编译并运行:

import Foundation
import CoreData

extension GameLog {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<GameLog> {
        return NSFetchRequest<GameLog>(entityName: "GameLog")
    }

    @NSManaged public var date: Date?
    @NSManaged public var id: UUID?
    @NSManaged public var totalPoints: Int32
    @NSManaged public var numberOfGames: Int32

   /* Calculated fields for game statistics */
     @objc dynamic var scorePerGame: Double {
         return Double(totalPoints) / Double(numberOfGames) 
     }

   var wrappedDate: Date {
        date ?? Date()
    }
    var wrappedID: UUID {
        id ?? UUID()
    }
   var wrappedPoints: Int32 {
        totalPoints
    }
    var wrappedNumberOfGames: Int32 {
        numberOfGames
    }
}

以下是代码的 sn-p,我在其中设置了 NSPredicate 和 NSSortDescriptor,它们将用于过滤和排序数据。这也可以正确编译和运行(在我将计算的属性标记为“@objc 动态”之后):

// Set how the results will be filtered and sorted
predicate = NSPredicate(format: "date >= %@", Calendar.current.date(byAdding: .day, value: -7, to: Date())! as NSDate)

switch  self.chosenStats {
case 0:  // Total points
     sortDescriptor = NSSortDescriptor(keyPath: \GameLog.totalPoints, ascending: false)
case 1:  // Games
    sortDescriptor = NSSortDescriptor(keyPath: \GameLog.numberOfGames, ascending: false)
default:  // Points per game
    sortDescriptor = NSSortDescriptor(keyPath: \GameLog.scorePerGame, ascending: false)
}

但是,当应用程序执行并应用排序过滤器时,它在前两种情况下工作正常(基于本机 CoreData 属性进行排序),但在第三种情况下(使用基于计算属性的 NSSortDescriptor ) 应用程序因可怕的“线程 1:信号 SIGABRT”错误而崩溃。

以下是我调用用于进行过滤和排序的视图的代码:

FilteredGameView(filterCriteria: self.predicate, sortCriteria: [self.sortDescriptor])

这是列出过滤和排序游戏的代码(简化)。如上所述,这在对原生 CoreData 属性(案例 0 和 1)进行排序时非常有效,但在计算的属性(案例 2)上则不行。

import SwiftUI

struct FilteredHOFView: View {

    var filteredGames: FetchRequest<GameLog>

    @Environment(\.managedObjectContext) var moc

    init(
        filterCriteria: NSPredicate,
        sortCriteria: [NSSortDescriptor]
    ) {
        self.filteredGames = FetchRequest(
            entity: GameLog.entity(),
            sortDescriptors: sortCriteria,
            predicate: filterCriteria
        )
    }


    var body: some View {
        List {
            ForEach(filteredGames.wrappedValue, id: \.self) { game in
                HStack {
                    Text("Show stats here")
                }
            }
        }
    }
}

对问题所在有什么想法吗?在应用 @objc 标记时我需要做些什么特别的事情吗?

【问题讨论】:

  • 报告的崩溃原因是什么?
  • 前两种情况没有得到错误,我能看到的唯一区别是(1)原生属性与计算字段,以及(2)Double vs Int32
  • 尝试用@objc dynamic标记计算属性
  • 伙计——你太棒了。那行得通。谢谢!!!!
  • 线程 1:致命错误:无法从 KeyPath Swift.KeyPath 中提取字符串 -

标签: swift sorting


【解决方案1】:

不幸的是,这似乎是不可能的。 Core Data 获取请求不能对计算属性进行排序,只能对持久存储属性进行排序。我在这个网站上发现了我之前忽略的以下问题。

Sorting NSFetchedResultsController by Swift Computed Property on NSManagedObjectSubclass

但是,如果有人知道,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多