[swift-evolution] [Pitch] Improving KeyPath

Logan Shire logan.shire at gmail.com
Fri Aug 25 17:54:24 CDT 2017


How would you feel about wrapping the existing functions
on _KVOKeyPathBridgeMachinery:

@nonobjc fileprivate static func _bridgeKeyPath(_ keyPath:AnyKeyPath) ->
String
@nonobjc fileprivate static func _bridgeKeyPath(_ keyPath:String?) ->
AnyKeyPath?

In extensions on String and AnyKeyPath respectively to instantiate strings
from KeyPaths and KeyPaths from Strings?

https://github.com/apple/swift/blob/c5ff1f2cac8da6a14330f4b033b94c7c926d2126/stdlib/public/SDK/Foundation/NSObject.swift#L84

On Fri, Aug 25, 2017 at 11:43 AM Joe Groff <jgroff at apple.com> wrote:

>
> > On Aug 23, 2017, at 11:18 PM, Logan Shire via swift-evolution <
> swift-evolution at swift.org> wrote:
> >
> > Hey folks!
> >
> > Recently I’ve been working on a small library which leverages the Swift
> 4 Codable protocol
> > and KeyPaths to provide a Swift-y interface to CoreData. (It maps back
> and forth between
> > native, immutable Swift structs and NSManagedObjects). In doing so I
> found a couple of
> > frustrating limitations to the KeyPath API. Firstly, KeyPath does not
> provide the name of the
> > property on the type it indexes. For example, if I have a struct:
> >
> >
> > struct Person {
> >    let firstName: String
> >    let lastName: String
> > }
> >
> > let keyPath = \Person.firstName
> >
> >
> > But once I have a keyPath, I can’t actually figure out what property it
> accesses.
> > So, I wind up having to make a wrapper:
> >
> >
> > struct Attribute {
> >    let keyPath: AnyKeyPath
> >    let propertyName: String
> > }
> >
> > let firstNameAttribute = Attribute(keyPath: \Person.firstName,
> propertyName: “firstName”)
> >
> >
> > This forces me to write out the property name myself as a string which
> is very error prone.
> > All I want is to be able to access:
> >
> >
> > keyPath.propertyName // “firstName”
> >
> >
> > It would also be nice if we provided the full path as a string as well:
> >
> >
> > keyPath.fullPath // “Person.firstName"
> >
> >
> > Also, if I want to get all of the attributes from a given Swift type, my
> options are to try to hack
> > something together with Mirrors, or forcing the type to declare a
> function / computed property
> > returning an array of all of its key path / property name pairings. I
> would really like to be able to
> > retrieve a type-erased array of any type’s key paths with:
> >
> >
> > let person = Person(firstName: “John”, lastName: “Doe”)
> > let keyPaths = Person.keyPaths
> > let firstNameKeyPath = keyPaths.first { $0.propertyName = “firstName” }
> as! KeyPath<Person, String>
> > let firstName = person[keypath: firstNameKeyPath] // “John"
> >
> >
> > And finally, without straying too far into Objective-C land, it would be
> nice if we could initialize key paths
> > with a throwing initializer.
> >
> >
> > let keyPath = try Person.keyPath(“firstName”) // KeyPath<Person, String>
> type erased to AnyKeyPath
> > let keyPath = AnyKeyPath(“Person.firstName”)
> >
> >
> > Let me know what you think about any / all of these suggestions!
>
> These would all be great additional features to eventually add to key
> paths. I think reflection mechanisms centered on key paths like what you
> describe would be a superior replacement for most of what Mirror attempts
> to provide.
>
> -Joe
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170825/21ae6696/attachment.html>


More information about the swift-evolution mailing list