【发布时间】: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
中提取字符串 -