I am talking about ARC projects.
I have always declared array properties like this
@property (strong, nonatomic) NSArray *myArray;
but I have seen a lot of people recommending using this:
@property (copy, nonatomic) NSArray *myArray;
People suggesting copy say "The copy on myArray is to prevent modification by another "owner" of the object you set." This "explanation" sounds klingon to me.
Can someone explain the meaning of this as I am 5 years old? OK, make it 3.
thanks
Copy is shallow, it only copies the pointer. If the array contains a mutable object and that object is changed the change will appear in the copied array.
NSMutableString *s = [@"test1" mutableCopy];
NSArray *a1 = @[s];
NSArray *a2 = [a1 copy];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);
[s appendString:@"2"];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);
Output:
a1: 0x10010fed0, (
test1
)
a2: 0x10010fed0, (
test1
)
a1: 0x10010fed0, (
test12
)
a2: 0x10010fed0, (
test12
)
The reason for the copy is for protection in the case where the array being copied is a mutable array so that any change of the original array will not change the copied array. The difference is a change in the mutable array and a change in an object in the mutable array. Note, the further reason is that one may not know that the array being assigned is mutable or not.
NSString *s1 = @"test1";
NSString *s2 = @"test2";
NSMutableArray *a1 = [@[s1] mutableCopy];
NSArray *a2 = [a1 copy];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);
[a1 addObject:s2];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);
Output:
a1: 0x100200510, (
test1
)
a2: 0x100200650, (
test1
)
a1: 0x100200510, (
test1,
test2
)
a2: 0x100200650, (
test1
)
Note that copy on an immutable NSArray just performs an assignment so there is no cost. There is only a copy made when the array being assigned is an NSMutableArray.
NSString *s1 = @"test1";
NSString *s2 = @"test2";
NSArray *a1 = @[s1];
NSArray *a2 = [a1 copy];
NSLog(@"\na1: %1$p, %1$@\na2: %2$p, %2$@", a1, a2);
Output:
a1: 0x100300140, (
test1
)
a2: 0x100300140, (
test1
)
The issue is that the array might mutate after setting the property, even though the property was defined as an immutable array. For example, consider,
NSMutableArray *array = [NSMutableArray arrayWithObjects:@1, @2, @3, nil];
obj.myArray = array;
[array addObject:@4];
If myArray
was defined as strong
, by changing the local mutable array would also change the myArray
property of obj
, too.
By defining myArray
as copy
, that ensures that you don't have to worry about the array itself mutating.
You still need to worry about the objects inside the array changing, and you might consider doing a deep copy if that's an issue, too.
Its simple, Consider somewhere in your view controller
NSArray *myArrayCopy = self.myArray
Now If myArray is strong then if you change some object in myArrayCopy myArray will automatically changed. while in case of copy it would not changed as it will assign copy of myArray to myArrayCopy.
It depends on whether you want to work on the same data or not. copy is indeed also "strong" so that the object will not be destroyed until the strong pointer is set to nil. But, strong references the same object while copy references a copy of the object. The generated setters would be something like:
-(void)setStrongArray:(NSArray*)data
{
_strongArray = data;
}
-(void)setCopyArray:(NSArray*)data
{
_strongArray = [data copy];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With