Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access property or method from a variable?

Tags:

ios

swift

Is it possible to access a method or property using a variable as the name of the method or property in Swift?

In PHP you can use $object->{$variable}. For example

class Object {
  public $first_name;
}

$object = new Object();
$object->first_name = 'John Doe';

$variable = 'first_name';
$first_name = $object->{$variable}; // Here we can encapsulate the variable in {} to get the value first_name
print($first_name);
// Outputs "John Doe"

EDIT:

Here is the actual code I'm working with:

class Punchlist {
    var nid: String?
    var title: String?

    init(nid: String) {

        let (result, err) = SD.executeQuery("SELECT * FROM punchlists WHERE nid = \(nid)")
        if err != nil {
            println("Error")
        }
        else {
            let keys = self.getKeys()  // Get a list of all the class properties (in this case only returns array containing "nid" and "title")
            for row in result {  // Loop through each row of the query
                for field in keys {  // Loop through each property ("nid" and "title")
                    // field = "nid" or "title"
                    if let value: String = row[field]?.asString() {
                        // value = value pulled from column "nid" or "title" for this row
                        self.field = value  //<---!! Error: 'Punchlist' does not have a member named 'field'
                    }
                }
            }
        }
    }

    //  Returns array of all class properties
    func getKeys() -> Array<String> {
        let mirror = reflect(self)
        var keys = [String]()
        for i in 0..<mirror.count {
            let (name,_) = mirror[i]
            keys.append(name)
        }

        return keys
    }
}
like image 797
balatin Avatar asked Dec 13 '14 01:12

balatin


2 Answers

Subscripting may help you.

let punch = Punchlist()
punch["nid"] = "123"
println(punch["nid"])

class Punchlist {
    var nid: String?
    var title: String?

    subscript(key: String) -> String? {
        get {
            if key == "nid" {
                return nid
            } else if key == "title" {
                return title
            }
            return nil
        }
        set {
            if key == "nid" {
                nid = newValue
            } else if key == "title" {
                title = newValue        
            }
        }
    }
}
like image 129
bluedome Avatar answered Sep 26 '22 22:09

bluedome


You can do it, but not using "pure" Swift. The whole point of Swift (as a language) is to prevent that sort of dangerous dynamic property access. You'd have to use Cocoa's Key-Value Coding feature:

self.setValue(value, forKey:field)

Very handy, and it crosses exactly the string-to-property-name bridge that you want to cross, but beware: here be dragons.

(But it would be better, if possible, to reimplement your architecture as a dictionary. A dictionary has arbitrary string keys and corresponding values, and thus there is no bridge to cross.)

like image 28
matt Avatar answered Sep 26 '22 22:09

matt