How to use "copy" property in Objective-C?

11,621

Solution 1

What the copy attribute does behind the scenes is to create a setter like this:

- (void)setMyCopiedProperty:(MyClass *)newValue {
    _myCopiedProperty = [newValue copy];
}

this means that whenever someone does something like this object.myCopiedProperty = someOtherValue;, the someOtherValue is sent a copy message telling it to duplicate itself. The receiver gets then a new pointer (assuming copy is correctly implemented), to which no-one excepting the receiver object has access to.

You can look at copy as being exclusive in some kind of way:

  • the clients that set the property don't have access to the actual set value
  • the receiver doesn't have access to the original passed value.

Beware of the caveats, though:

  • a copied NSArray doesn't copy its objects, so you might end up thinking that a @property(copy) NSArray<MyClass *> *myProperty is safe, however while the array itself is safe from being modified, the objects held by the array share the same reference. Same is true for any collection class (NSDictionary, NSSet, etc)
  • if the property matches to a custom class you need to make sure the copy method does its job - i.e. creating a new object. This happens for all Cocoa/CocoaTouch classes that conform to NSCopying, however for other classes this might or not be true, depending on implementation (myself I didn't saw yet a class that lies about its copy method, however you never know)

Solution 2

Try this:

Model.h

@interface Model: NSObject

@property (nonatomic,strong)NSString *firstName;

@property (nonatomic,copy) NSString *lastName;

@end

ViewController.m

-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
Model *model = [[Model alloc]init];
NSMutableString *str = [[NSMutableString alloc]initWithString:@"test"];
model.firstName = str;
model.lastName = str;
NSLog(@"%@, %@", model.firstName, model.lastName);
[str appendString:@"string"];
NSLog(@"%@, %@ ", model.firstName, model.lastName);}


Output :
 1st Nslog = "test", "test" 
 2nd Nslog = "teststring", "test"

Solution 3

An instance of a class is a discrete copy. When you assign an instance of a class to be the value of a property with the copy attribute, a clone of that instance is made and that clone becomes the value of the property. There is no relationship between the original and its clone, so the property does not have access to the original instance at all. Changing an attribute of the property's value is changing the clone.

Note:

If you implement the setter for a copy property, it is your responsibility to ensure it actually creates a copy. As is true with all the attributes for a property, they only have meaning when the compiler is generating (synthesizing) the setter and/or getter for you.

Share:
11,621

Related videos on Youtube

user2457766
Author by

user2457766

Updated on June 04, 2022

Comments

  • user2457766
    user2457766 almost 2 years

    I have read through many materials online which all explain when people should use "copy" instead of "strong".

    "The copy attribute is an alternative to strong. Instead of taking ownership of the existing object, it creates a copy of whatever you assign to the property, then takes ownership of that. Only objects that conform to the NSCopying protocol can use this attribute..."

    And there are plenty of example codes showing when using "copy", the original value stays the same.

    However, I'm new to Objective-C. I really want to know how to use the newly assigned value. Where is the "new instance(copy)" with the "new value"? Do I need any additional methods to change the original value if I want to?

    It will be great if someone can share an example for this part not the one proving the original value is not changed, which is everywhere.

    • Chenya Zhang
      Chenya Zhang over 7 years
      @Paulw11 What do you mean by "you don't have a reference to the original object"? I found examples online logging out the original value using the original reference. Could you give an example? I'm also confused about where the new value is and how to use it.
    • Paulw11
      Paulw11 over 7 years
      Say I have NSString *a="1234"; If I assign a to a copy property b then what the setter code does is effectively b = [a copy] so now B is a new string. If I change a, nothing will happen to b, since b is a copy. Similarly if I change b then nothing happens to a.
  • Rahul Gupta
    Rahul Gupta over 5 years
    @Sneha in first NSlog it will print "test", "test" but in 2nd NSlog it will print "teststring", "test" because "copy" is needed when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object