Swift: Converting a String into a Variable Name

Swift: Converting a string into a variable name

Short Answer: There is no way to do this for good reason. Use arrays instead.

Long Answer:
Essentially you are looking for a way to define an unknown number of variables that are all linked together by their common format. You are looking to define an ordered set of elements of variable length. Why not just use an array?

Arrays are containers that allow you to store an ordered set or list of elements and access them by their ordered location, which is exactly what you're trying to do. See Apple's Swift Array Tutorial for further reading.

The advantage of arrays is that they are faster, far more convenient for larger sets of elements (and probably the same for smaller sets as well), and they come packaged with a ton of useful functionality. If you haven't worked with arrays before it is a bit of a learning curve but absolutely worth it.

Swift, use string name to reference a variable

How about using a dictionary, [String : Int]?

This will allow you to achieve what you want - storing values for different keys.

For example, instead of using

var d1000 = 0
var d1289 = 0
var d1999 = 0

You could use

var dictionary: [String : Int] = [
"d1000" : 0,
"d1289" : 0,
"d1999" : 0
]

To store a value in the dictionary, just use

dictionary[key] = value
//for example, setting "d1289" to 1234
dictionary["d1289"] = 1234

and to get the value from the dictionary, use

let value = dictionary[key]
//for example, getting the value of "d1289"
let value = dictionary["d1289"]

So, you could use something like this

//initialize your dictionary
var myDictionary: [String : Int] = [:]

//your key initialization data
var deviceIDtype: Character = "d"
var deviceIDsection: String = "12"
var deviceID: String = "89"
var ref: String = ""

//your code
func devName(/*...*/){/*...*/}
ref = devName(/*...*/)

//set the key ref (fetched from devName) to 1234
myDictionary[ref] = 1234

Just as a side note, you could really clean some of your code

func devName(type: Character, section: String, id: String) -> String{      
return String(type) + section + id
}

//...

let key = devName(deviceIDtype, section: deviceIDsection, id: deviceID)
let value = 1234
myDictionary[key] = value

Convert the text of a string to a variable name?

Azurlake had the right idea, try passing into the function an object of class A1Square instead of String.

If you don't want to do this, and if A1Square is a node, you can use the SpriteKit method childNodeWithName:. If you call this on the square's parent node and use the string for the square's name, it will return the child node for that name.

For instance, if you added the square to self you could say:

let node: SKSpriteNode = self.childNodeWithName(square) as SKSpriteNode
if (piece == "whiteKing") {node.texture = whiteKing}

Convert Swift variable name to string, to use as string?

You can make this a function instead of a variable, and do the same thing. I'll explain it in steps.

So first, how do we make a function the same thing as a variable?

Basically, we are "wrapping" the variable inside of the function. This is a similar to approach to the first block I suggested in your latest RefBool thread, where we grabbed or set a value via function.

Here, we are using methods/functions to alter a variable directly without parameters--so, we will be using the function by name instead of using the variable by name to access it throughout our code:

enum Static {
private static var _button1 = false
static func button1() { toggle(&_button1) }
}

Note, the Enum is just a namespace for us to call the method to emphasize that the variable's name is not needed for our code to work--Only the function needs to know its name.This code would work inside of a struct or class as well, or even in a global namespace.

So here, if I want to change the value of _button1, I must call button1(). _button1 is essentially invisible to everyone and everything--and that's ok, because we only need button1() to do our work.

So now, every time we call Static.button1() , Static._button1 will toggle true to false, false to true, and so on (using the function I gave you earlier)


Why are we doing this?

Well, because there is no way to get the name of a variable without Mirror and reflection, and there is already a built-in command called #function. We are jumping through the added hoop of using the function, so we don't have to set-up a mirror and other OBJc hoops.

Let's alter our enum to demonstrate how we can get the name of the func:

 enum Static {
private static var _button1 = false

static func button1() -> String {
toggle ( &_button1 )
return ( #function )
}
}

Now, when we call button1(), we do two things: 1, we toggle the state of the button (_button1), and we return a string with the name "button1()"

let buttonName = Static.button1()  // buttonName = "button1()"

We can make this more usable by calling a member of String to mutate itself:

let trimmedButtonName = Static.button1().replacingOccurrences(of: "()", with: "")
// trimmedButtonName = "button1"

Let's update our enum now with this handy replacement:

enum Static {
private static var _button1 = false

static func button1() -> String {
toggle ( &_button1 )
return ( #function.replacingOccurrences(of: "()", with: "") )
}
}

And our final use case is as follows:

let buttonName = Static.button1()


Note:

You don't have to have _button1 as private, that was just to demonstrate that you don't need it to be public. If you need to grab the state of it, you can make another function, or return a tuple type from button1():

static func button1() -> (name: String, state: Bool) {
// ...
return ( #function.etc, _button1)
}

let results = Static.button1()
print( results.name ) // "button1"
print( results.state ) // true / false

You can also set something in the parameter if you need more explicit control over setting the variable, just as you would any normal function.


UPDATE:

For example, if you wanted to use explicit control, you could do:

func button1(equals: Bool? = nil) -> (name: String, state: Bool) {
if equals != nil {
// do the code mentioned above
} else {
_button1 = equals!
}

return (#function.replacingOccurrences(of: "()", with: ""), _button1)
}

let buttonState.state = Static.button1(equals: false) // false
let buttonStateAgain.state = Static.button1(equals: true) // true
print(Static.button1().name) // "button1"

String as Member Name in Swift

Swift is a strongly typed language, and iterating in a python/javascript like approach is less common and less recommended.
Having said that, to my best knowledge you have three ways to tackle this issue.

First, I'd suggest encoding the CoreData model into a dictionary [String: Any] or [String: String] - then you can keep the same approach you wanted - iterate over the property names array and get them as follow:

let dic = object.asDictionary()
ForEach(strings){ str in
//Want to pass in string here as property name
let propertyValue = dic[str]
//This doesn't work because string cannot be directly passed in as property name - this is the essence of my question.

}

Make sure to comply with Encodable and to have this extension

extension Encodable {
func asDictionary() throws -> [String: Any] {
let data = try JSONEncoder().encode(self)
guard let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] else {
throw NSError()
}
return dictionary
}

Second, you can hard coded the properties and if/else/switch over them in the loop

ForEach(strings){ str in
//Want to pass in string here as property name
switch str {
case "first_name":
// Do what is needed

}

}

Third, and last, You can read and use a technique called reflection, which is the closest thing to what you want to achieve
link1
link2

Get a Swift Variable's Actual Name as String

As per the updated from this answer, it is supported in Swift 3 via #keyPath

NSPredicate(format: "%K == %@", #keyPath(Person.firstName), "Andrew")

how would I convert a string stored in a variable into executable code text in swift?

Swift does not have an eval function like Lisp. You can't create a bunch of Swift code as a string and then execute it at runtime. Instead you need to parse the string yourself and evaluate it.

This isn't trivial, but Nick Lockwood has created a very nice library called Expression that does it. You don't have to use that library, but it's a very good introduction to how to solve the problem. It's about 1500 lines of Swift, and you can work through how it tokenizes and evaluates strings in a pretty straightforward way. (It has some performance optimizations, and it would probably be easier to understand without that, but I still expect you can work your way through with a little work.)

If you want to build this kind of thing from scratch, it is common to first explore building an RPN (Reverse Polish Notation) calculator. This is a stack-based calculator, and is generally much easier to implement than an "infix" calculator. Instead of 1 + 2 you would enter 1 2 +, and the + always consumes the last two values on the stack. If you're trying to get into parsers and evaluators, RPN is a great place to start. It's just a lot simpler to implement.

There is also the built-in NSExpression that will do this for you and is built-in, but it's a pain to work with in Swift, and I don't really recommend it, unless you just need something very quick.

Print passed variable name in funciton parameter argument as string (Swift)

There is no way for printValue func to know that you passed a value named positionX because printValue knows only about a variable named variable.
What you could do is changing the printValue func passing also the variable name as a String. E.g:

func printValue(_ value: Double, _ name: String) {
print("\(name) = \(value)")
}

and call it like:

override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad starts here")
let poisitionX: Double = 5.7
printValue(positionX, "positionX")
}

How to print variable name in swift?

You could change your struct to an enum

enum API: String {
case apiEndPoint = "example.com/profile?"
case apiEndPoint1 = "example.com/user?"
}


func doSomething(endPoint: API) {
print("\(endPoint): \(endPoint.rawValue)")
}

Example

doSomething(endPoint: .apiEndPoint)

apiEndPoint: example.com/profile?



Related Topics



Leave a reply



Submit