I'm trying to use "Self.displayOrder" in a protocol extension, but it raises the following error "Thread 1: Fatal error: Could not extract a String from KeyPath Swift.ReferenceWritableKeyPath"
Here's the code
protocol Listable where Self: NSManagedObject {
static func sortedFetchRequest() -> NSFetchRequest<Self>
var displayOrder: Int { get set }
}
extension Listable {
static func sortedFetchRequest() -> NSFetchRequest<Self> {
let req: NSFetchRequest<Self> = NSFetchRequest(entityName: String(describing: Self.self))
req.sortDescriptors = [NSSortDescriptor(keyPath: \Self.displayOrder, ascending: true)]
return req
}
}
final class OwnerModel: NSManagedObject, Identifiable, Listable {
@NSManaged var displayOrder: Int
}
You need to declare the protocol with @objc
:
@objc protocol Listable where Self: NSManagedObject {
var displayOrder: Int { get set }
}
This will tell the compiler to use the Objective-C runtime when processing the keypath, and will allow the conversion from a Swift KeyPath
to the string needed by SortDescriptor
.
One note, sortedFetchRequest
had to be removed from the protocol definition, as default implementations for protocol requirements is not possible in the protocol is @onjc, since default implementation is statically dispatched, while an @objc protocol is dinamically dispatched. This doesn't prevent you from using the default implementation, though, in Swift code.