<div dir="ltr">How would you feel about wrapping the existing functions on _KVOKeyPathBridgeMachinery:<div><br><div>@nonobjc fileprivate static func _bridgeKeyPath(_ keyPath:AnyKeyPath) -&gt; String</div><div>@nonobjc fileprivate static func _bridgeKeyPath(_ keyPath:String?) -&gt; AnyKeyPath?</div><div><br></div><div>In extensions on String and AnyKeyPath respectively to instantiate strings from KeyPaths and KeyPaths from Strings?</div><div><br></div><div><a href="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</a><br></div><div><br><div class="gmail_quote"><div dir="ltr">On Fri, Aug 25, 2017 at 11:43 AM Joe Groff &lt;<a href="mailto:jgroff@apple.com">jgroff@apple.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
&gt; On Aug 23, 2017, at 11:18 PM, Logan Shire via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br>
&gt;<br>
&gt; Hey folks!<br>
&gt;<br>
&gt; Recently I’ve been working on a small library which leverages the Swift 4 Codable protocol<br>
&gt; and KeyPaths to provide a Swift-y interface to CoreData. (It maps back and forth between<br>
&gt; native, immutable Swift structs and NSManagedObjects). In doing so I found a couple of<br>
&gt; frustrating limitations to the KeyPath API. Firstly, KeyPath does not provide the name of the<br>
&gt; property on the type it indexes. For example, if I have a struct:<br>
&gt;<br>
&gt;<br>
&gt; struct Person {<br>
&gt;    let firstName: String<br>
&gt;    let lastName: String<br>
&gt; }<br>
&gt;<br>
&gt; let keyPath = \Person.firstName<br>
&gt;<br>
&gt;<br>
&gt; But once I have a keyPath, I can’t actually figure out what property it accesses.<br>
&gt; So, I wind up having to make a wrapper:<br>
&gt;<br>
&gt;<br>
&gt; struct Attribute {<br>
&gt;    let keyPath: AnyKeyPath<br>
&gt;    let propertyName: String<br>
&gt; }<br>
&gt;<br>
&gt; let firstNameAttribute = Attribute(keyPath: \Person.firstName, propertyName: “firstName”)<br>
&gt;<br>
&gt;<br>
&gt; This forces me to write out the property name myself as a string which is very error prone.<br>
&gt; All I want is to be able to access:<br>
&gt;<br>
&gt;<br>
&gt; keyPath.propertyName // “firstName”<br>
&gt;<br>
&gt;<br>
&gt; It would also be nice if we provided the full path as a string as well:<br>
&gt;<br>
&gt;<br>
&gt; keyPath.fullPath // “Person.firstName&quot;<br>
&gt;<br>
&gt;<br>
&gt; Also, if I want to get all of the attributes from a given Swift type, my options are to try to hack<br>
&gt; something together with Mirrors, or forcing the type to declare a function / computed property<br>
&gt; returning an array of all of its key path / property name pairings. I would really like to be able to<br>
&gt; retrieve a type-erased array of any type’s key paths with:<br>
&gt;<br>
&gt;<br>
&gt; let person = Person(firstName: “John”, lastName: “Doe”)<br>
&gt; let keyPaths = Person.keyPaths<br>
&gt; let firstNameKeyPath = keyPaths.first { $0.propertyName = “firstName” } as! KeyPath&lt;Person, String&gt;<br>
&gt; let firstName = person[keypath: firstNameKeyPath] // “John&quot;<br>
&gt;<br>
&gt;<br>
&gt; And finally, without straying too far into Objective-C land, it would be nice if we could initialize key paths<br>
&gt; with a throwing initializer.<br>
&gt;<br>
&gt;<br>
&gt; let keyPath = try Person.keyPath(“firstName”) // KeyPath&lt;Person, String&gt; type erased to AnyKeyPath<br>
&gt; let keyPath = AnyKeyPath(“Person.firstName”)<br>
&gt;<br>
&gt;<br>
&gt; Let me know what you think about any / all of these suggestions!<br>
<br>
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.<br>
<br>
-Joe</blockquote></div></div></div></div>