Question
Hi !
I have been looking for a way to constraint a generic type in a function or type to be a property marked with @NSManaged
or at least @objc
. Unfortunately I could not find anything tangible. Thus I would like to ask here if anyone knows if such a solution exists.
Here is an exemple of what I would like to achieve.
class User: NSManageObject {
@NSManaged var isAdmin
var isAuthenticated: Bool { !isAdmin }
func request<V>(for keyPath: KeyPath<User, V>) where V: NSManaged {
// ...
}
}
user.request(for: \.isAdmin) // should compile
user.request(for: \.isAuthenticated) // should not compile
Context and motivation
I am working on a library named SafeFetching to build NSPredicate
s and NSFetchRequest
s with a DSL.
The goal is to offer a safe way to build such predicates to avoid a a runtime crash and to use types in the expression while being as expressive as possible.
I am satisfied with the results. For instance, here is an imaginary example of what I was able to achieve so far.
User.request()
.all(after: 10)
.where(\.isAdmin && \.score == 10
|| \.name * .hasPrefix("Jo")
)
.nsValue // NSFetchRequest
But there is catch. I use NSExpression(forKeyPath:)
to get the label: String
property from the NSExpression
. But it only works on types that can be used with Objective-C. This is fine as long as the targeted property is an attribute of the entity - which is often the case. But I would prefer to enforce the @NSManaged
mark to avoid runtime crash to be able to really call this library "Safe".
Related topics
I have found this thread where the concept of ObjCKeyPath
is evoked, but it did not lead to a solution I could use.
I hope this the right place to ask such a question. Otherwise please let me know.