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
, and c
是对其的引用。
When a
在步骤 2 中进行修改,Swift 给出a
和数组的新副本以及b
and 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
.
当createFredsFriends()
返回,并且对数组的唯一引用由局部变量保存friends
在步骤 2 中,数组的所有权已被传递。
在步骤 3 中,对数组的第二个引用已分配给friends
的财产fred
.
在第 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()