I have an array var arr = [myObject]
I want to copy it to arr2
so that modifying object in the second the first remained as is (copy by value). How to make it?

- 449
- 2
- 9
- 25
-
I believe this was answered here: https://stackoverflow.com/questions/30066274/swift-how-to-copy-an-array-that-contains-reference-types – Martin Muldoon Apr 07 '18 at 12:02
-
Your desired behaviour luckily is the default behaviour of Swift values types (e.g. Array). So whenever you assign an array to a new variable, you can modify it without affecting the original. – dr_barto Apr 07 '18 at 12:07
-
1Not if the array contains reference types. – Martin Muldoon Apr 07 '18 at 12:08
-
A proper answer depends on what you have in the array. Does your array contain classes. structs, or enums? – rmaddy Apr 07 '18 at 16:45
3 Answers
If the type within your array is an enum or a struct, no problem. You don't need to think about it:
var a = [1,2,3]
var b = a
b[1] = 3
b // [1, 3, 3]
a // [1, 2, 3]
If your array contains a class then you do need to think about how you copy objects, because by default you will be working with pointers to the same instances:
let ns = NSMutableArray()
var arr = [ns]
var arr2 = arr
arr2[0].add(2)
arr[0] // [2]
But where classes adopt the NSCopying
protocol you can use copy() and mutableCopy() to make the necessary copies to resolve this:
var arr3 = arr.map(){$0.mutableCopy() as! NSMutableArray}
arr3[0].add(1)
arr3[0] // [2, 1]
arr[0] // [2]
arr2[0] // [2]
Where a class does not adopt the NSCopying
protocol, you will need to extend or subclass, adding a copy(with:)
method:
extension UIView: NSCopying {
public func copy(with zone: NSZone? = nil) -> Any {
return UIView(frame: self.frame)
}
}
var aView = UIView(frame:CGRect(x: 0, y: 0, width: 100, height: 100))
var bView = aView.copy() as! UIView
aView.tag = 5
bView.tag // 0
aView.tag // 5
Note: The code example of copying a UIView is incredibly simplistic and assumes that a "copy" is simply a view the same size, whereas a copy in real use would be something more complex, most likely containing subviews, etc.

- 5,746
- 1
- 33
- 56
actually the simplest way was to make:
var arr2:[myObject] = Array(arr1)
P.S. thanks to all for suggestions

- 449
- 2
- 9
- 25
-
let updatedMyArray:[MyObject] = Array(self.MyArray) not wroking for me, – Shahid Aslam Feb 15 '19 at 07:37
You can do that by creating a computed property. And then lazy load it to declare as a class variable.
lazy var secondArray :[myObject] = { return firstArray }()
Now if you ever need second array, it will get you first array

- 5,163
- 2
- 21
- 38