1

I plan to use a class object variable to capture user entered data sets in recurring cycles and when a data set is complete add this to an array holding all these class variables. Simple example code in playground:

class Example {
    var a = 1
    var b = 5
}

var exArray = [Example] () //  this is the array holding the class variables
var anExample = Example () // default-init the "re-usable" variable

exArray.append(anExample)

exArray[0].a // results in 1 as expected
exArray[0].b //  results in 5 as expected
exArray.count // 1 as expected

// now changing the re-usable variable properties with new user entered data

anExample.a = 3
anExample.b = 7

// appending the altered variable

exArray.append(anExample)

exArray[0].a // shows 3 where I still expect 1
exArray[0].b // shows 7 where I expect 7
exArray.count // shows 2 as expected

it seems the array holds the variable itself (pointer?) not a copy of the variable, so this keeps changing within the array. Any ideas how I can "reset" the class variable without changing the array member?

swiftML
  • 11
  • 2
  • Create a new instance of Example before setting new attributes value. `anExample = Example() anExample.a = 3 anExample.b = 7` – Francescu Sep 29 '14 at 20:23
  • Thanks, Francescu. To create a new instance I would have to give the variable another name, so can't access the same name variable. If I use the same name I can't "re-instance" it, so changing properties such as a or b will still change the original class object anExample even as member of the array - which is what I don't want – swiftML Oct 01 '14 at 16:28
  • You can do what I told you. But if you don't want to create another instance within the same variable name as I suggested you should consider use a Struct instead of a Class. As stated in the Swift language reference, Struct are passed through their values and Classes are passed through their references. – Francescu Oct 01 '14 at 19:35
  • Did that eventually and this works well, thank you – swiftML Oct 05 '14 at 19:19

2 Answers2

2

If you create an instance of a class and assign to a variable, the variable contains a reference to the instance and not the instance itself.

When you add the variable to the array, you add the reference to the class instance. If you later change the instance properties and add to the array, you add the same reference as you added before. Result: all of what you insert into the array is a variable containing a reference to the same class instance.

Depending on your app architecture and logic, you might want to turn the class into a struct - differently from a class, which is a reference type, the struct is a value type, so when moved around, a copy of it is created. That happens when:

  • you assign the variable to another variable
  • you pass it to a function or method (unless the inout modifier is used)

As a direct consequence, if you insert a struct instance into an array, you call a method, so a copy of the struct is created and inserted into the array - that copy has no relationship with the original struct, besides having the same values at the moment it is copied. So any change you do to any of them, it is not reflected to the other.

Antonio
  • 71,651
  • 11
  • 148
  • 165
2

If you want your data copied when you assign it, you can define Example as a struct instead of a class See this answer for the difference between struct and class

struct Example {
    var a = 1
    var b = 5
}

Now when you assign it to the array, it will add a copy to the array with the data at the point where you assigned it.


But if you want to keep using a class you should create a new instance with the data you want before you append it to the array.

Community
  • 1
  • 1
Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
  • Many thanks Alex and Antonio. I wanted the class for inheritance but there are workaround options. Will try with struct instead and feed back how this works – swiftML Sep 30 '14 at 19:28
  • I have tried the struct option; this creates problems with the functions/methods in the class, as struct methods seem to unable to modify self properties from within (that's the error code listed by Xcode). Have therefore applied the instancing of a separate class object for each array member. This indeed works well, although it doesn't appear to be very elegant. many thanks again for the advice – swiftML Oct 01 '14 at 16:24
  • 2
    Define your struct methods as `mutating func` and those methods will be able to alter their own struct. – Alex Wayne Oct 01 '14 at 16:34