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:
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?
Swift's codes are easy to read and write. Swift algorithms are easy to read and write, similar to Java, JavaScript, and other C languages. Swift is a modern programming language with a relatively simplified and concise syntax.
C function pointers are imported into Swift as closures with the C function pointer calling convention, denoted by the @convention(c) attribute. For example, a function pointer that has the type int (*)(void) in C is imported into Swift as @convention(c) () -> Int32 .
According to Apple, Swift is approximately 2.6 times faster than Objective C. The speed calculated generally relates to the speed of coding. Swift's syntax is much more simple and direct than Objective-C. This enables developers to focus on the core part of the code rather than the rules on which the codes are based.
As the performance of swift, it is 2.6x faster than Objective C and 8.4x faster than python. It got an encouraging syntax that make you write clean and consistent code. It provides improve readability and prevent errors.
Yes you can. I've used this as a solution for the next scenario: When I print an object/struct in the console, I like to see the vars names along with associated values:
extension CustomStringConvertible {
var description: String {
var description = "\n ***** \(type(of: self)) *****\n"
let mirrorS = Mirror(reflecting: self)
for child in mirrorS.children {
if let propertyName = child.label {
description += " \(getSpaces(forWord: propertyName))\(propertyName): \(child.value)\n"
}
}
return description
}
}
And to use this, let's have as an example the following struct:
public struct FavoriteApp: Codable, CustomStringConvertible, Hashable {
let appId: String
let appName: String
let bundleId: String
let image: NSImage
let isMacApp: Bool
let rating: String
let screenshotUrls: [String]
let sellerName: String
let sellerUrl: String
let releaseDate: String
let genres: String
let latestVersion: String
}
let anApp:FavoriteApp = getTheAppInfoFromServer()
print(anApp)
// This will print into console:
// ***** FavoriteApp *****
// appId: 1438547269
// appName: Dynamic wallpaper
// bundleId: com.minglebit.DynamicWallpaper
// image: -not visible- (but is there, trust me :))
// isMacApp true
// rating: 0
//
// screenshotUrls: https://is1-ssl.mzstatic.com/image/thumb/Purple128/v4/5c/08/b8/5c08b824-12eb-e0b6-22fb-0e234f396b9e/pr_source.jpg/800x500bb.jpg
// https://is1-ssl.mzstatic.com/image/thumb/Purple128/v4/f3/34/0e/f3340e21-714c-0a17-4437-73ba1828cbba/pr_source.jpg/800x500bb.jpg
// sellerName: MingleBit SRL
// sellerUrl: https://minglebit.com/products/dynamicwallpaper.php
// releaseDate: 2018-10-18T14:59:47Z
// genres: Entertainment, Lifestyle
// latestVersion: 2.3
So, to concentrate the answer, use Mirror(reflecting: object)
to get what you want.
If you are only dealing with URLs, it is recommended to use URLComponents, which is better.
model:
struct QueryObject{
var params = [String: String]()
var getUrl: String{
let result = "www.ScoreTracker.com/postScore"
guard var url = URL(string: result) else { return result}
url.appendQueryParameters(params)
return url.absoluteString
}
init(params: [String: String]) {
self.params = params
}
}
then:
let params = ["userName": "Maverick", "highScore": "123456"]
let queryObject = QueryObject(params: params)
let urlString = queryObject.getUrl
DDLog(urlString) //www.ScoreTracker.com/postScore?userName=Maverick&highScore=123456
Github link
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With