given a string, can you access a property (in a class) that has that same name?

ok... the deal is: I want to make a flexible object, that has to access properties in another class, that have the same type.

then I'll make an array of these objects and give them each a different property name to manage:


var watchKey : String = "propertyName"


given a string with the correct name for a property, can you access that property in swift? something like:

object.propertyNamed(someString)

?

Accepted Reply

So, time has passed and I have learned something.


if, like me, you are deriving your classes from NSObject, then there is a way to enable the Obj-c functionality. I would expect that it adds some overhead, but it also saves you the headache of writing the code yoruself.


how? add @objc to the front of your property declaration.

then 2 magical functions in NSObject become useful:


    func setValue(_ value: Any?, forKey key: String) 
    func value(forKey key: String) -> Any?


then my original question is answered, and I've avoided trying to come up with a new naming pattern for those functions.

Replies

I would try to use dictionary to store the references.


Found this: is it something in the direction you are looking for ?


https://stackoverflow.com/questions/27454625/how-to-access-property-or-method-from-a-variable


But I understand you are looking for something more direct.

hrmmm... there was support for this in Objective-C to some extent, and my "flexible class design" just finds itself in a corner that would be served very well if this functionality pre-existed.


but that's ok. a dictionary is a large burden for other reasons outside of this discussion, but I think I've come up with a solution.

I have to build an itermediate object in any case, and I'm just going to add 2 functions to that class:


setValue(_ value, forProperty: String)
getValue(_ forProperty: String)->Any?


and hard code a switch that tests the forProperty, and behaves as expected.

it's not a generalized solution, but it's more than enough for my needs.

So, time has passed and I have learned something.


if, like me, you are deriving your classes from NSObject, then there is a way to enable the Obj-c functionality. I would expect that it adds some overhead, but it also saves you the headache of writing the code yoruself.


how? add @objc to the front of your property declaration.

then 2 magical functions in NSObject become useful:


    func setValue(_ value: Any?, forKey key: String) 
    func value(forKey key: String) -> Any?


then my original question is answered, and I've avoided trying to come up with a new naming pattern for those functions.

I’m not sure I understand your requirements correctly, but it seems like you should be able to create a type-safe solution using key paths. For example:

class A {
    var propertyX: String = "Hello"
    var propertyY: String = "Cruel"
    var propertyZ: String = "World!"
}

let watchKey = [
    \A.propertyX,
    \A.propertyY,
    \A.propertyZ,
]
let object = A()
for key in watchKey {
    let s = object[keyPath: key]
    print(s)
}
// prints…
//
// Hello
// Cruel
// World!

Critically, the type of

s
in line 14 is
String
, not
Any
.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi eskimo,

the short answer is: no.

I've spent a good part of the day trying to learn enough about KeyPaths to intelligently respond to your suggestion. I've learned nothing of value. I do suspect that KeyPaths are innappropriate for my approach... But I can't even articulate why, because I couldnt even tell you what a KeyPath is, or what it does. I see some 3rd party examples, but I see no actual documentation. Sure, there's a place in the docs that says KeyPath, but it doesn't actually tell you anything. So I'm stuck trying to duplicate what I see, and making small changes to test how the idea of KeyPaths is supposed to work. And frankly... small changes always result in compiler errors. In fact, KeyPaths was one of the things that made using NSObserver so difficult, that forced me to eventually home-brew my very own observation system, which is why I have a String (the name of the property that is changed) that I need to somehow use to directly access the property.


and if the one benefit to using the keyPath approach is type safety... this shouldn't come as a shock... Swift is type safe, Swift with Cocoa, or Foundation is not. We get hit with optionals and Any all the time... to get work done we are forced to use curly brackets, deeply nested if statements, and coersion (as!) all the time.


so in the end: KeyPath, might be a very interesting way to leverage data, if only it were clear what it is and what it does.


And this is a real pervasive problem with a LOT of recent Apple technology: I assume it's all very magical and useful, it's just incredibly unclear.

IMO the place to learn about key paths is the Swift Evolution proposal that introduced them, SE-0161 Smart KeyPaths: Better Key-Value Coding for Swift.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

therein lies the problem.

that is a proposal, in a language design forum. It is couched in a highly inflected, coloquial version of english that is not taught or referenced ANYWHERE. In order to properly be able to understand Everything that is written there, one has to understand this Coloquial english, and in order to do that, You'd have to have been on the ground floor of the design and implementation of Swift in the first place. It lacks Any Kind of context, or bootstrapping cues.


And please... send up the flares and red flags as high as they will go... this is a global crit that Apple needs to hear and address post haste as a Unit: You have it Baked into the DNA of the Company now that You do not adequately document _ANYTHING_ on the developer's side of things, and when 3rd party devs do not learn or even know about such things, they do not adopt them... which is why the next killer app never arises. You are functionally killing your tech, by failing to create ocuments that make it a least "possible" to learn.


I did learn one thing from that link, that I did not know beforehand. But I am completely snowed under by something else, and as always there are no examples of something that should be relatively easy:


I have a variable:

let keyPath  = \noWay.virtualFooBear

that I can then use like this:

let virtualVal = aWay[keyPath: keyPath]


I can then extend that into an Array (no example because it's dead obvious)

But when I try to expand to a Dictionary:

let thePaths = [ "v" : \noWay.virtualFooBear, "fooBear" : \noWay.fooBear ]

it does not work.

let virtualVal = aWay[keyPath: thePaths["v"]]

***** out with the error : Value of type 'noWay' has no subscripts



it's in a playground :

import UIKit

var str = "Hello, playground"


class noWay : NSObject {
     var fooBear : String = "magical foo bear"
     var virtualFooBear : String{
        get { return "virtual" + fooBear }
        set { fooBear = newValue }
    }
}

let aWay = noWay()

aWay[keyPath: \noWay.virtualFooBear] = "boobooHiss"

let keyPath  = \noWay.virtualFooBear
let thePaths = [ "v" : \noWay.virtualFooBear, "fooBear" : \noWay.fooBear ] //: [ String : KeyPath<noWay, String>]

let virtualVal = aWay[keyPath: thePaths["v"]]


using a dictionary is a good compromise stop-gap approach to trying to get into KeyPaths without throwing our hundreds of hours of work already done. But here's the thing: functionally, I'm not doing anything that should trigger an error, and if I am... the error is meaningless, and the proposal does not address anything to do with this error, so I cannot know how to fix it. I tried putting together a type for the dictionary hoping that it would silence the error... nope. I'm just guessing. "KeyPath<noWay, String>" doesn't actually mean anything to me. I've converted something I found online to the best approximation I could manage... And that's part of the overall problem, because Swift is a very opaque language when you get down to it. I'm experiencing Compoud levels of poorly documented or undocumented features in the Swift language that require me to learn things that are themselves poorly documented or not documented.


documentation is a deliberate step in the process of communicating with 3rd party developers, and Apple is not doing it. Granted: I am probably dumber than others, but I'm also smarter than others, and more willing to put in the effort. Don't reward me with pointlessly steep learning curves.

I solved my error despite an opaque error message (the dictionary was returning an optional) and tried to work the "solution" into the project.

instantly I run into yet another insrutable error.


if this is going to be the way it "works," I'm done with KeyPath.


it does not work, It provides zero advantages over the Obj-C approach (aside from potentially being faster)


it is Not type safe. I have been forced to declare the type myself to silence errors.

It does not meet the original spec : accessing a property with a String (which is apparently impossible with KeyPath)

and, it cannot recover from accessing a dictionary declared in a superClass, which is the final straw.


KeyPaths are magical technology, I'm sure. ring me back when they are documented, provide error messages that are clear, and don't bomb out under reasonable usage.

It sounds like you have an inherently dynamic operation. I think you are correct. That approach is not going to be compatible with key paths. I'm not a Swift developer myself, but I saw a presentation today on Swift and realized that the presenter was essentially using a Swift enum along with generics to provide the same functionality as dynamic types. That might be an approach you could use. Swift has a very powerful enum system and I think it is pretty funny that people are using it as a way to support dynamic behaviour.


Although that link was originally a Swift language proposal, it has since been updated to have a status of "implemented" in Swift 4.


Otherwise, I'm afraid your complaints about documentation are futile. Apple has plenty of app developers. The one developer here, or a thousand developers there, abandon the platform, it would have no noticable impact compared to the 2 million new developers at the end of the year. Except for a few holdouts, Swift has completely taken over with iOS developers and hiring managers.