【问题标题】:Swift Object reference to array?Swift对象对数组的引用?
【发布时间】:2016-06-27 09:28:50
【问题描述】:

我可能错过了有关 swift 的重要信息。我有一个地图包含一个键/快速数组对。我改变了数组,地图里面的数组没有改变。有人可以解释发生了什么吗?谢谢!

var map = [String:[String]]()
var list = [String]()
map["list"] = list //output: "["list": []]\n"
print(map)

list.append("test")
print(list)  //output: "["test"]\n"
print(map)   //output: "["list": []]\n"

【问题讨论】:

  • Swift 数组是按值传递的,即复制过来。您必须将其设置回地图中,或使用某种参考包装器:stackoverflow.com/questions/24250938/…
  • 我使用了包装类来获得这个功能。我确实想知道是否有一种方法可以使用指向数组的指针,然后从其他地方的指针创建一个数组。
  • 没有办法在 Swift 中为数组使用指针,因为它不能那样工作。
  • “在 Swift 中没有办法为数组使用指针”这并不完全正确。

标签: arrays swift


【解决方案1】:

如您所知,这些(字典和数组)是value types。所以一般来说,您正在寻找的技术只是将数组从字典中取出,修改它,然后再放回去:

var map = [String:[String]]()
map["list"] = [String]()

var list = map["list"]!
list.append("test")
map["list"] = list

但是,还有另一种方法:您可以获得一种指向字典中数组的指针,但前提是您使用带有inout 参数的函数。例如:

var map = [String:[String]]()
map["list"] = [String]()

func append(s : String, inout to arr : [String]) {
    arr += [s]
}
append("test", to: &(map["list"]!))

这实际上只是对同一事物的一种表示法,但如果您要做很​​多这样的事情,您可能会更喜欢它。

【讨论】:

【解决方案2】:

假设我们在 Swift 中有一个 class 类型:

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

这里我们看到指针样式的行为:aClass 和 bClass 指向同一个对象。如果您更改其中一个的属性值,那么两者都会更改,因为它们是相同的。

结构

使用struct 时行为会发生变化,如下所示:

struct MyStruct {
    var a:Int
    init(i:Int) {
        a = i
    }
}
let aStruct = MyStruct(i: 10)
var bStruct = aStruct
bStruct.a = 20
aStruct.a // 10

使用struct(和enum)而不是单个实例和指向该实例的多个指针,当我们将值分配给新实例时会创建一个新实例。它是原件的副本,它们彼此独立。

数组类型

由于 Swift Array 类型是 struct,它具有复制而不是指向的行为。虽然NSArrayNSMutableArray 仍然是类(如在ObjC 中),但class 的指向行为也是如此。

使结构表现得像一个类

您已经看到其他人发布了有关 inout 属性的帖子,您还可以使用计算变量来部分复制指针的行为:

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"]

在类型实例之外,您可以执行以下操作:

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

【讨论】:

    【解决方案3】:

    Swift 中的数组被定义为结构体,即值类型。当您将另一个变量分配给另一个值类型的变量时,它会创建第二个变量的副本:

    map["list"] = list   // store a **copy** of list into map
    

    要查看值和引用类型之间的区别,请将您的数组更改为它的 ObjectiveC 表亲 NSMutableArray,它是引用类型:

    var map = [String: NSMutableArray]()
    var list = NSMutableArray()
    map["list"] = list
    
    list.addObject("test")
    
    print(map)   // ["list": (test)]
    

    【讨论】:

      【解决方案4】:

      正如Code Different 所说,Swift 中的数组是结构体,因此您存储的是数组的副本。

      如果你真的想继续使用 Swift 数组,我建议先填充数组“list”,然后复制到“map”。这应该对你有用。

      【讨论】:

        猜你喜欢
        • 2021-01-12
        • 2017-03-12
        • 1970-01-01
        • 1970-01-01
        • 2019-10-03
        • 2021-01-15
        • 1970-01-01
        • 2014-12-06
        • 1970-01-01
        相关资源
        最近更新 更多