Ok, there's an existing question here on S/O with the following title:
Swift: Get Variable Actual Name as String
By it's name, it seems that's exactly what I want. However, looking at the accepted answer (and the other non-accepted ones), they are referring to key path manipulation, which isn't what I'm after. (i.e. This is not a duplicate!)
In my case, I want the name of one variable to be stored in a second variable of type string.
In C#, this is trivial using nameof
, like so...
int someVar = 3
string varName = nameof(someVar)
// 'varName' now holds the string value "someVar"
Note:
nameof()
executes at compile-time, not run-time so no reflection or anything else is needed. The compiler simply subs in the name of the variable as if someone manually typed its name as a string constant.
It's pretty handy when you, for instance, want to define a query object where your member names match the query parameters passed in a URL.
Here's a pseudo-code example (i.e. this clearly won't compile, but shows what I'm after.)
Also, please don't focus on the URL aspects of this. This is definitely *bad code*. In real code I'd use URLComponents
, not string-append a URL like I'm doing here. Again, this is *only* illustrating my question, not building URLs.
struct queryObject{
let userName : String
let highScore : Int
var getUrl:String{
return "www.ScoreTracker.com/postScore?\(nameof(userName))=\(userName)&\(nameof(highScore))=\(highScore)"
}
}
Here's how you'd use it and what it would return:
let queryObject = QueryObject(userName:"Maverick", highScore:123456)
let urlString = queryObject.getUrl
The return value would be:
www.ScoreTracker.com/postScore?userName=Maverick&highScore=123456
The advantages of having access to a string representation of a variable, instead of using string constants are many:
- No hard-coded strings.
- You can use refactoring/renaming of symbols as usual and the generated strings track
- Allows you to keep your API and implementation in sync which aids in readability.
For instance, say the API changed the query param from userName
to userId
, all one would have to do is refactor the variable name and the output would update accordingly without having to manually touch any strings.
So, can this be done in Swift? Can you get the actual variable name and store it in a second variable?
String
to encode URLs. You'll have a much easier time withURL
. Also, take a look atURLComponents
andURLQueryItem
for a better way of generating urls with parameters. – Billhook#keyPath
perhaps comes close to it (but requires@objc
properties and classes), andMirror(reflecting:)
can do something at runtime. The Swift 4KeyPath
has no string representation (https://mcmap.net/q/329204/-getting-string-from-swift-4-new-key-path-syntax/1187415). – On the other hand, if the actual purpose is to encode/serialize a custom structure then the Swift 4Codable
protocol might be utilized, have a look at some JSONEncoder examples. – StraddleCodable
in your (actual) use case? Here's a quick example of how you could build a URL query encoder: gist.github.com/hamishknight/d1cabdf19cce90ca8458da9294562542 – Smilacaceousnameof
in the scenario you pictured, because I wouldn't want an innocent renaming to break my query string. – Billhook#name(...)
literal that can be applied to an expression referring to a declaration (such as a property): github.com/hamishknight/swift/commit/… :) – Smilacaceous