views:

1268

answers:

4

I'm declaring an NSString property in a class and objective-c is complaining that:

NSString no 'assign', 'retain', or 'copy' attribute is specified

It then casually lets me know that "assign is used instead".

Can someone explain to me the difference between assign, retain and copy in terms of normal C memory management functions?

+4  A: 

Cocoa uses reference counting to manage memory. Objects with a reference count of 0 are deleted.

  • assign - does nothing to reference count simply points your variable to the data
  • retain - points your variable to data and adds 1 to reference count, data is guaranteed to be there while your variable is still alive
  • copy - makes a copy of data, points your variable at it and makes the retain count 1

More detail here, at Apple's own documentation.

bmalicoat
retain - __even if__ someone [ deallocs ] the NSString you are referencing? Or does it only work if every user of that same instance [ releases ] ?
bobobobo
@bobobobo - you should *never* call `dealloc` yourself. You should *always* use `release` or `autorelease`.
Dave DeLong
What Dave said. The reason your data is guaranteed is because you assume everyone else only uses release, lowering the reference count by just their reference. If other people, or you yourself, pass dealloc or over release an object (thereby not following the rules) your data is not guaranteed!
bmalicoat
+6  A: 

I think it is drawing your attention to the fact that a assign is being used, as opposed to retain or copy. Since an NSString is an object, in a reference-counted environment (ie without Garbage Collection) this can be potentially "dangerous" (unless it is intentional by design).

However, the difference between assign, retain and copy are as follows:

  • assign: In your setter method for the property, there is a simple assignment of your instance variable to the new value, eg:

    - (void)setString:(NSString*)newString
    {
        string = newString;
    }
    

    This can cause problems since Objective-C objects use reference counting, and therefore by not retaining the object, there is a chance that the string could be deallocated whilst you are still using it.

  • retain: this retains the new value in your setter method. For example:

    - (void)setString:(NSString*)newString
    {
        [newString retain];
        [string release];
        string = newString;
    }
    

    This is safer, since you explicitly state that you want to maintain a reference of the object, and you must release it before it will be deallocated.

  • copy: this makes a copy of the string in your setter method:

    - (void)setString:(NSString*)newString
    {
        if(string!=newString)
        {
            [string release];
            string = [newString copy];
        }
    }
    

    This is often used with strings, since making a copy of the original object ensures that it is not changed whilst you are using it.

Perspx
+3  A: 

assign - the ivar is set by doing a simple assignment. Implementation:

- (void) setFoo:(NSString *)newFoo {
  foo = newFoo;
}

retain - the ivar is sent the retain message before doing the assignment. Implementation:

- (void) setFoo:(NSString *)newFoo {
  if (foo != newFoo) {
    [foo release];
    foo = [newFoo retain];
  }
}

copy - the ivar is sent the copy message before doing the assignment. Implementation:

- (void) setFoo:(NSString *)newFoo {
  if (foo != newFoo) {
    [foo release];
    foo = [newFoo copy];
  }
}
Dave DeLong
These are not the actual implementations the compiler @synthesizes, but demonstrate behavior from a (non GC) memory management perspective.
Nikolai Ruhe
@Nikolai - yes, thanks for clarifying.
Dave DeLong
+1  A: 

See also The Objective-C Programming Language for the official word on what each of those terms means in a property declaration.

Sixten Otto