Як я можу зробити точний дублікат масиву?
Мені важко знайти інформацію про дублювання масиву в Swift.
Я спробував використовувати .copy()
var originalArray = [1, 2, 3, 4]
var duplicateArray = originalArray.copy()
Як я можу зробити точний дублікат масиву?
Мені важко знайти інформацію про дублювання масиву в Swift.
Я спробував використовувати .copy()
var originalArray = [1, 2, 3, 4]
var duplicateArray = originalArray.copy()
Відповіді:
Масиви мають повноцінну семантику в Swift, тому не потрібно нічого фантазії.
var duplicateArray = originalArray
це все, що вам потрібно.
Якщо вміст масиву є еталонним типом, то так, це скопіює покажчики лише на ваші об’єкти. Щоб виконати глибоку копію вмісту, замість цього слід використовувати map
та виконувати копію кожного примірника. Для класів Foundation, які відповідають NSCopying
протоколу, ви можете використовувати copy()
метод:
let x = [NSMutableArray(), NSMutableArray(), NSMutableArray()]
let y = x
let z = x.map { $0.copy() }
x[0] === y[0] // true
x[0] === z[0] // false
Зауважте, що тут є підводні камені, над якими семантика значень Свіфта працює над тим, щоб захистити вас, наприклад, оскільки він NSArray
представляє собою незмінний масив, його copy
метод просто повертає посилання на себе, тож тест, наведений вище, дасть неочікувані результати.
var x = [UIView(), UIView(), UIView()] var y = x for i in x { NSLog("%p", i) } println("---") for i in y { NSLog("%p", i) }
і я отримав такий вихід: 0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770 ---0x7fa82b0009e0 0x7fa82b012660 0x7fa82b012770
Не схоже, що його копіюють, чи знаєте ви чому?
x[0] == x[1]
але x[0] === y[0]
повинна бути невдалою
Нейт правильно. Якщо ви працюєте з примітивними масивами, все, що вам потрібно зробити, це призначити duplicateArray для originalArray.
Для повноти, якби ви працювали об'єктом NSArray, ви зробите наступне, щоб зробити повну копію NSArray:
var originalArray = [1, 2, 3, 4] as NSArray
var duplicateArray = NSArray(array:originalArray, copyItems: true)
Існує третій варіант відповіді Нейт:
let z = x.map { $0 } // different array with same objects
* РЕДАКТИВАНО * редагування починається тут
Вище по суті те саме, що нижче, і фактично використання оператора рівності нижче буде краще, оскільки масив не буде скопійовано, якщо він не буде змінено (це за задумом).
let z = x
Детальніше читайте тут: https://developer.apple.com/swift/blog/?id=10
* Редаговано * редагування закінчується тут
додавання або видалення до цього масиву не вплине на початковий масив. Однак зміна будь-яких властивостей будь-якого з об'єктів, якими володіє масив, буде видно у вихідному масиві. Тому що об'єкти в масиві не є копіями (якщо припустити, що масив містить об'єкти, а не примітивні числа).
var array1: [String] = ["john", "alan", "kristen"]; print(array1); var array2 = array1.map { $0 }; print(array2); array2[0] = "james"; print(array1); print(array2);
NSCopying
, то дублюйте масив:let z = x.map { $0.copy as! ClassX }
Для звичайних об'єктів можна зробити реалізацію протоколу, який підтримує копіювання, і змусити клас об'єктів реалізувати цей протокол так:
protocol Copying {
init(original: Self)
}
extension Copying {
func copy() -> Self {
return Self.init(original: self)
}
}
А потім розширення Array для клонування:
extension Array where Element: Copying {
func clone() -> Array {
var copiedArray = Array<Element>()
for element in self {
copiedArray.append(element.copy())
}
return copiedArray
}
}
і це майже все, щоб переглянути код і зразок перевірити цю суть
object's
init
Якщо ви хочете скопіювати елементи масиву якогось об’єкта класу. Тоді ви можете слідувати наведеному нижче коду без використання протоколу NSCopying, але вам потрібно мати метод init, який повинен приймати всі параметри, необхідні для вашого об'єкта. Ось код для прикладу тестування на дитячому майданчику.
class ABC {
var a = 0
func myCopy() -> ABC {
return ABC(value: self.a)
}
init(value: Int) {
self.a = value
}
}
var arrayA: [ABC] = [ABC(value: 1)]
var arrayB: [ABC] = arrayA.map { $0.myCopy() }
arrayB.first?.a = 2
print(arrayA.first?.a)//Prints 1
print(arrayB.first?.a)//Prints 2
var duplicateArray = originalArray