4

I'm following an official tutorial Your second iOS App:Storyboard and it told me to declare a property masterBirdSightingList like this(just a specific example and not necessary to know the context) :

@property (nonatomic, copy) NSMutableArray *masterBirdSightingList;

Note that there's an attribute copy. and then synthesize this property :

@synthesize masterBirdSightingList = _masterBirdSightingList;

And next there's one init method which made me confused :

- (void)initializeDefaultDataList {
NSMutableArray *sightingList = [[NSMutableArray alloc] init];
self.masterBirdSightingList = sightingList;
[self addBirdSightingWithName:@"Pigeon" location:@"Everywhere"];
}

Definitely sightingList is allocated for spaces and then it's assigned to the masterBirdSightingList property. The property has a copy attribute, though. it means the instance variable _masterBirdSightingList would be allocated for another space to preserve stuffs from sightingList. Why? Why not directly allocate space for the property like this :

self.masterBirdSightingList = [[NSMutableArray alloc] init];
lookof
  • 363
  • 1
  • 3
  • 8
  • I wonder know the statement self.masterBirdSightingList = sightingList is just a simple copy operation that only copies the reference OR it will allocate a new space to store the content? thx – lookof May 23 '12 at 17:26
  • 3
    Something worth watching out for: generally, a "mutable" object’s -copy method will return the non-mutable variant (in your case, an NSArray). In order to prevent an exception, you have to write the setter method yourself to call -mutableCopy. – David Cairns May 23 '12 at 17:49

1 Answers1

8

In Objective-C, the copy attribute in a property means the setter synthesized will look like this:

-(void)setMasterBirdSightingList:(NSMutableArray*)newValue
{
    if (_masterBirdSightingList == newValue) return;
//  NSMutableArray* oldValue = _masterBirdSightingList;
    _masterBirdSightingList = [newValue copy];
//  [oldValue release];    // <-- not applicable in ARC.
}

and that dot syntax will always be translated to

[self setMasterBirdSightingList:sightingList];

regardless of the attribute of the property.

The "allocated for another space to preserve stuffs from sightingList" stuff is done via the -copy method. The way you pass the argument to the setter's newValue parameter is irrelevant.


Edit: As @David mentioned in the comment, the -copy method of a mutable type returns an immutable object. You have to override the setter to call -mutableCopy instead. See What's the best way to use Obj-C 2.0 Properties with mutable objects, such as NSMutableArray?.

Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • I would hope the compare would be with `isEqual:`. – Hot Licks May 23 '12 at 18:10
  • @HotLicks: No they should not be compared with `-isEqual:`. The `==` exists mainly to avoid double-release when `-copy` returns the same value (possible with immutable types) and you are using `self.foo = self.foo`. – kennytm May 23 '12 at 18:25
  • 1
    I looked at the tutorial, and it does include instructions on overriding the setter to preserve mutability. – jscs May 23 '12 at 18:32