Swift 在处理数组时使用 ARC(自动引用计数),它会延迟复制数组,直到其中一个副本被修改:
例如:
var a = [1, 2, 3, 4, 5]
let b = a
let c = a // 1
a.append(6) // 2
print(a.count)
print(b.count)
print(c.count)
在上面的步骤 1 中,内存中只有一个 [1, 2, 3, 4, 5] 的副本,a、b 和 c 是对它的引用。
当a在步骤2中被修改时,Swift给出a和数组的新副本,b和c继续引用原始数组。所以现在内存中有2个数组副本。
让我们看一个更复杂的例子:
class Person: CustomStringConvertible {
let name: String
var friends: [Person] = []
init(name: String) {
self.name = name
}
var description: String { return name }
}
func createFredsFriends() -> [Person] {
let barney = Person(name: "Barney")
let wilma = Person(name: "Wilma")
let betty = Person(name: "Betty")
let friends = [barney, wilma, betty] // 1
return friends
}
func createFred() -> Person {
let fred = Person(name: "Fred")
let friends = createFredsFriends() // 2
fred.friends = friends // 3
return fred
}
let fred = createFred() // 4
print(fred.friends) // [Barney, Wilma, Betty]
在步骤 1,创建朋友数组。它被局部变量friends引用。
1234563 /li>
在第 3 步,对数组的第二个引用已分配给 fred 的 friends 属性。
在第 4 步,createFred() 已返回,因此局部变量 friends 已消失,不再引用该数组。唯一的引用是在fred 对象的属性中,该对象由变量fred 持有。
所以数组创建了一次,创建了几个对它的引用,最后只有一个对数组的引用,所有这一切都是在没有一次复制操作的情况下完成的。
由于 Swift 数组是值类型并且在更改时被复制,所以您不能传递一个数组,然后期望在复制时更新原始数组。如果您需要该级别的功能,您可以为数组创建一个类包装器,然后始终通过该类的实例访问该数组。
这里我修改了前面的例子来展示它是如何工作的:
// Class to wrap array so that everyone references the same copy
class FriendsWrapper {
var friends: [Person]
init(friends: [Person]) {
self.friends = friends
}
}
class Person: CustomStringConvertible {
let name: String
var friendsWrapper: FriendsWrapper?
init(name: String) {
self.name = name
}
func addFriend(friend: Person) {
if let wrapper = friendsWrapper {
wrapper.friends.append(friend)
} else {
friendsWrapper = FriendsWrapper(friends: [friend])
}
}
var description: String { return name }
}
func createFredsFriends() -> [Person] {
let barney = Person(name: "Barney")
let wilma = Person(name: "Wilma")
let betty = Person(name: "Betty")
let friends = [barney, wilma, betty]
return friends
}
func createFred() -> Person {
let fred = Person(name: "Fred")
let friendsWrapper = FriendsWrapper(friends: createFredsFriends())
fred.friendsWrapper = friendsWrapper
// Add friend to Fred object
fred.addFriend(Person(name: "Bam Bam"))
// Copy of array in local friendsWrapper is updated
print(friendsWrapper.friends) // [Barney, Wilma, Betty, Bam Bam]
return fred
}
let fred = createFred()