[swift-evolution] [Pitch] Improving KeyPath

Joe Groff jgroff at apple.com
Fri Aug 25 18:08:35 CDT 2017


> On Aug 25, 2017, at 3:54 PM, Logan Shire <logan.shire at gmail.com> wrote:
> 
> 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?

Those functions are designed for Cocoa interop only. They're not going to produce results that make sense for all Swift key paths.


-Joe

> https://github.com/apple/swift/blob/c5ff1f2cac8da6a14330f4b033b94c7c926d2126/stdlib/public/SDK/Foundation/NSObject.swift#L84 <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 <mailto:jgroff at apple.com>> wrote:
> 
> > On Aug 23, 2017, at 11:18 PM, Logan Shire via swift-evolution <swift-evolution at swift.org <mailto: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/acc242bb/attachment.html>


More information about the swift-evolution mailing list