Class
Let's suppose we have a type that is a class
in Swift:
class MyClass {
var a:Int
init(i:Int) {
a = i
}
}
let aClass = MyClass(i: 10)
var bClass = aClass
bClass.a = 20
aClass.a // 20
aClass.a = 30
bClass.a // 30
Here we see pointer-style behaviour: aClass and bClass are pointing at the same object. If you change a property value in one of them then both change, because they are the same.
Struct
The behaviour changes when a struct
is used, as can be seen here:
struct MyStruct {
var a:Int
init(i:Int) {
a = i
}
}
let aStruct = MyStruct(i: 10)
var bStruct = aStruct
bStruct.a = 20
aStruct.a // 10
With a struct
(and an enum
) instead of there being a single instance and multiple pointers to that instance, a new instance is created when we assign the value to a new instance. It is a copy of the original and they are independent of one another.
Array type
Since the Swift Array type is a struct
it has the behaviour of copying rather than pointing. While NSArray
and NSMutableArray
remain classes (as in ObjC) and so have the pointing behaviour of a class
.
Making a struct behave like a class
You've already seen others post about inout properties, and you can also use computed variables to partially replicate the behaviour of a pointer:
struct MyStruct {
lazy var map = [String:[String]]()
var list:[String] {
mutating get {
if map["list"] == nil {
map["list"] = [String]()
}
return map["list"]!
}
set {
map["list"] = newValue
}
}
}
var mS = MyStruct()
mS.list = ["test"]
mS.map // ["list": ["test"]]
mS.list // ["test"]
While outside a type instance you might do the following:
var map = [String:[String]]()
var list = [String]()
var appendToList = { (a:String) in
list.append(a)
map["list"] = list
}
appendToList("test") // list and map["list"] are both updated