Swift Object reference to array?

前端 未结 4 1228
面向向阳花
面向向阳花 2021-01-18 18:30

I probably missed an important information about swift. I have a map contains a key / swift array pair. I changed the array and the array inside the map was not changed. Cou

4条回答
  •  遇见更好的自我
    2021-01-18 18:41

    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
    

提交回复
热议问题