@property (copy) vs method [ copy]

Viewed 47

Is there any difference between (A) and (B) below?
(Assume NON ARC, if it matters)

// --- (A) ---
@interface Zoo : NSObject{}
@property (copy) Dog *dog;
@end
//..... then somewhere
someZoo.dog = another_dog;
// --- (B) ---
@interface Zoo : NSObject{}
@property (assign) Dog *dog;
@end
//..... then somewhere
someZoo.dog = [another_dog copy];

If the answer is negative, is there any advantage of using (A)?
I find approach (B) less error prone, since the explicit code shows exactly what is going on, but I'm not expert, hence the question.

2 Answers

The difference between A and B is that in B you have to remember to use copy everywhere you assign dog, whereas with A takes care of that for you. B is more fragile.

And the other consideration is that with A, you can glance at the interface and understand the memory semantics, whereas with B, you have to pour through the whole implementation of Zoo to deduce what’s going on.

And, of course, as Davyd points out (+1), you wouldn’t use assign. It should be copy if using copy semantics or retain if not.

Assuming non-ARC:

Approach A is correct: you have a strong property with copy, Zoo retains the instance of Dog upon assignment, it should also release it in dealloc. This ensures correct memory management: copy returns retain count = 1, in dealloc it returns to 0 and the instance of Dog is deallocated.

Approach B is incorrect. Although, it will work in this case, it's ultimately wrong. The Zoo object needs to decide whether to retain the instance of dog or not. In your case the retain count of Dog is controlled outside of Zoo class - ultimately against the principle (see below). This leads to several potential problems.

  1. Memory leak if the Zoo object does't release the dog in dealloc. In fact, according to conventions, it shouldn't because the property is declared with 'assign' attribute.

  2. Crash due to dead instance in case somewhere else in the code somewhere uses assignment like:

someZoo.dog = another_dog

The first access to the dog property inside Zoo will crash, since Zoo hasn't retained the dog, which might be released elsewhere.

You need to decide whether the Zoo class needs to retain an instance of dog or not. Normally the answer would be 'yes', except for the cases when it leads to retain loops. Since the Zoo owns the dog, the Zoo must have a strong (retain or copy) relationship, but the Dog must keep assign back to the Zoo.

Naturally, if Zoo uses retain or copy attribute for the property it must release it in dealloc. The Dog must not retain or release the Zoo ever.

Also, the principle is simple: The object that receives an instance decides whether to retain it or not. If it retains that instance, it must release it eventually.

Related