Jonathan Tuzman
Jonathan Tuzman

Reputation: 13262

Pass a reference to an instance variable?

I want a method to set a value for an instance variable but I want to tell it which variable to set the value for each time I call the function.

var first: Key!
var second: Key!

func setKey(for selectedKey: Key) {
    let key = // key selected from picker 
    selectedKey = key
}

func someWhereElse() {
    setKey(for: first)
    setKey(for: second)
}

Key is a class so it’s a reference type. Am I understanding reference mechanics right or is what I want a reference to the reference? (Some kind of C type pointer)

Upvotes: 0

Views: 504

Answers (3)

Cosmos Man
Cosmos Man

Reputation: 603

It should be

func setKey(for reference: inout Key!) {
   let key = // key value you want to set
   reference = key
}  

Then you can invoke the method as following,

setKey(for: &yourKeyValue)

If you want to point the reference to class object's instance member

setKey(for: &(yourObject.yourVariable) )

According to your code, it will be

var first: Key!
var second: Key!

func setKey(for selectedKey: inout Key!) {
    let key = // key selected from picker 
    selectedKey = key
} 

func someWhereElse() {
    setKey(for: &first)
    setKey(for: &second)
}

Note the inout attribute in parameters. This is very much like pointer in C.
In your case, classes are like already pointing to some kind of memory block (* Key). So, what you need is pointer to pointer (** Key). This can be done with inout Key or UnsafeMutablePointer<Key>. As Swift doesn't encourage usage pointers, inout Key should be used for safety.

Note that if you want to point to Key!, it should be inout Key!.
If for Key, it should be inout Key.
Key and Key! are not the same.

If you want to work with Unsafe Swift, here is the code

func setKey(for reference: UnsafeMutablePointer<Key!>) {
   let key = // key value you want to set
   reference.pointee = key
}

then you can call it the same way as inout,

setKey(for: &yourValue)

Upvotes: 2

Robert May
Robert May

Reputation: 819

If the class that contains the instance variable is not a subclass, you can have it inherit NSObject so that it contains the setValue(_ value: Any?, forKey: String) method. You can then set the value of an instance variable of an instance of said class with a string as the key.

As for your understanding of reference mechanics, you are right that first and second would be passed by reference. However, if you change the value of selectedKey, you are not changing the value of first or second, you are changing the reference. selectedKey holds the reference, so to change the value of the object it references, you must change its properties, for example selectedKey.value = key. Changing the value of selectedKey itself changes the reference, so the object it is referencing will not be changed.

Upvotes: 1

Shahrukh Malik
Shahrukh Malik

Reputation: 252

One solution is make variable identifier in Key class.

Set

first.identifier = 1
second.identifier = 2

Check this value in setKey method to identify the instance variable

Second solution is in setKey method, check reference

if first === selectedKey {
   // First Instance

} else if second === selectedKey {
   // Second Instance

} else {
   print("the two instances are not identical!")
}

Upvotes: 1

Related Questions