Reputation: 1883
When I am copying the object with copy command in iOS (swift / objective c), Will that be a shallow copy or a deep copy ?
var str = "Hello, playground"
var copyStr = str.copy()
and
var originalArray = [1, 2, 3, 4] as NSArray
var copyArray = originalArray.copy()
withUnsafePointer(to: &originalArray) {
print(" originall address: \($0)")
}
withUnsafePointer(to: ©Array) {
print(" copy address: \($0)")
}
Help me with the lines above , is this a deep copy or a shallow copy ?
The issue is , this behaviour in objective c is showing me the same address with both string and array which is shallow copy and in swift3 it is showing me different address which is deep copy
Upvotes: 2
Views: 978
Reputation: 437432
The copy
performs a shallow copy (a copy of the collection, but the objects in the array are not copied). E.g.
let obj1 = Object(value: 1)
let obj2 = Object(value: 2)
let obj3 = Object(value: 3)
let originalArray = [obj1, obj2, obj3] as NSArray
let copyArray = originalArray.copy() as! NSArray
print(String(format: "original address: %p", originalArray))
for obj in originalArray {
print(String(format: " %p", obj as! Object))
}
print(String(format: "copy address: %p", copyArray))
for obj in copyArray {
print(String(format: " %p", obj as! Object))
}
Note, I use an object other than NSNumber
and NSString
, as those have optimizations that may make looking at addresses misleading.
The member objects of these two arrays point to the same objects (i.e. a shallow copy).
original address: 0x618000044920
0x6180000277e0
0x618000027f00
0x618000027ea0
copy address: 0x618000044920
0x6180000277e0
0x618000027f00
0x618000027ea0
In fact, as you can see, because it's an immutable NSArray
, it appears to optimize this where the copy is actually returning the same array instance. If you use mutable arrays, NSMutableArray
, you'll see two unique arrays returned, as you'd expect, but they will still point to the same collection of objects.
But, if you use NSArray(array:copyItems:)
with true
for copyItems
, you will get two unique arrays with unique copies of each member object:
let copyArray = NSArray(array: originalArray as! [Any], copyItems: true)
That yields a deep copy (two unique arrays where the individual member objects are copied and they, too, have unique addresses):
original address: 0x618000059e60
0x618000027ae0
0x618000028340
0x618000028280
copy address: 0x61800005ba20
0x618000028800
0x618000028aa0
0x618000028400
See the documentation for init(array:copyItems:)
which says:
The
copy(with:)
method performs a shallow copy. If you have a collection of arbitrary depth, passingtrue
for theflag
parameter [ofinit(array:copyItems:)
] will perform an immutable copy of the first level below the surface. If you passfalse
the mutability of the first level is unaffected. In either case, the mutability of all deeper levels is unaffected.
Personally, though, if writing Swift, I'd generally use Array
and Dictionary
value types rather than the old NSArray
and NSDictionary
types.
Upvotes: 3
Reputation: 21
String in Swift are Value Types. For all Value Types, a new copy of the existing String value is created.
From Apple Document.
Swift’s copy-by-default String behavior ensures that when a function or method passes you a String value, it is clear that you own that exact String value, regardless of where it came from. You can be confident that the string you are passed will not be modified unless you modify it yourself.
Hope this helps
Upvotes: 0