Мое понимание:
Массивы в Swift являются типами значений. Массивы и другие коллекции в Swift имеют механизм CoW (Копировать при записи), поэтому, когда массив передается в качестве аргумента функции или просто присваивается другой переменной, Swift фактически не создает другую копию массива, а просто передает ссылку на тот же массив , При попытке записать / изменить массив, swift создаст новую копию массива (при условии, что ссылка на исходный массив все еще удерживается), и операция записи будет выполнена для новой копии массива.
Справочная информация:
В этой задаче я пытаюсь сохранить экземпляры классов (ссылочные типы в массиве)
class TestClass {
var name: String = "abcd"
init(name: String) {
self.name = name
}
}
Я создаю локальную переменную a (массив) TestClass
и передав его в качестве аргумента someFunc
override func viewDidLoad() {
super.viewDidLoad()
var a = [TestClass(name: "abcd"), TestClass(name: "efgh"), TestClass(name: "ijkl")]
debugPrint(UnsafePointer(&a))
self.someFunc(array: a)
}
В someFunc
я присваиваю аргумент другой переменной anotherArray
и выполняю append
операцию с anotherArray
. Как и ожидалось, CoW of Array запускается и создает новую копию Array, поэтому адреса памяти array
и anotherArray
отличаются.
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
debugPrint(UnsafePointer(&array))
debugPrint(UnsafePointer(&anotherArray))
}
Как и ожидалось, при копировании типа значения все внутренние ссылочные типы также будут воссозданы / скопированы, чтобы доказать, что
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
for var value in array {
debugPrint(UnsafePointer(&value))
}
for var value in anotherArray {
debugPrint(UnsafePointer(&value))
}
}
Очевидно, что адреса памяти массивов различны (array !=== anotherArray
), а также адреса памяти всех элементов внутри array
и anotherArray
также различны (array[i] !=== anotherArray[i]
)
Проблема:
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
anotherArray[0].name = "Sandeep"
debugPrint(array[0].name)
}
При ясном понимании, что array и anotherArray - это две разные копии, а также ссылочные типы внутри каждого массива совершенно разные, можно было бы ожидать, если бы я изменил значение anotherArray[0].name
на "Sandeep" , array[0].name
все еще должно быть "abcd", но возвращает "Sandeep"
Почему это так? Я что-то здесь упускаю? Имеет ли это какое-либо отношение к Special Accessor Array mutableAddressWithPinnedNativeOwner
?
Специальный метод доступа к массиву mutableAddressWithPinnedNativeOwner
Если я правильно понимаю, вместо того, чтобы просто извлекать значение по указанному c индексу, копировать его, изменять его и заменяя исходное значение, как в случае Dictionary , mutableAddressWithPinnedNativeOwner
, просто обращайтесь к физической памяти значения по указанному c index и модифицируйте его. Но это не должно иметь значения, когда весь массив модифицируется: | Запутался здесь
Полный рабочий код:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var a = [TestClass(name: "abcd"), TestClass(name: "efgh"), TestClass(name: "ijkl")]
debugPrint(UnsafePointer(&a))
self.someFunc(array: a)
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
func someFunc(array: [TestClass]) {
var anotherArray = array
anotherArray.append(TestClass(name: "mnop"))
for var value in array {
debugPrint(UnsafePointer(&value))
}
for var value in anotherArray {
debugPrint(UnsafePointer(&value))
}
anotherArray[0].name = "Sandeep"
debugPrint(array[0].name)
}
}