views:

81

answers:

4

In my setter I have a incoming string that I am copying to avoid any trouble should the original be modified.

- (void)setName:(NSString *)newName{
    if(name != newName) {
     [name release];
     name = [newName copy];
    }
}

My question is: as I am doing a copy where should I release it, or do I just do an autorelease? i.e.

- (void)setName:(NSString *)newName{
    if(name != newName) {
     [name release];
     name = [[newName copy] autorelease];
    }
}

gary

+6  A: 

When you do a copy, the object will be retained. This is what you want. If you autorelease it, it will be deallocated eventually. So your first example is correct. The second one will crash your app.

If you're worried about what happens when the object is deallocated, remember that you should release any references in your dealloc method.

Alex
You may also want to consider using a property such as:@property(copy, readwrite) NSString *value;
Malaxeur
Yep. For a simple property like this, you're better served by letting the runtime generate the accessors for you. They're usually better than the accessors you'd write for yourself, anyway.
Alex
Yes. The copy gets stored in the variable `name` with reference count 1, and that object gets released in `setName:` before you create your new copy.
Alex
Ah I think I understand, its an increment to the retain count of the object not a duplicate. Am I right in thinking that the copy pushes the retain count to +1, but if you call set again with a different object the old one is released (retain count-1) and the new object incremented (with a retain count of +1). I think I get it :)
fuzzygoat
If you're not using GC, you still have to balance the copy with a release, even if you use @synthesized methods.
Barry Wark
@fuzzygoat: Your understanding of copy is not right. Copy creates a copy (at least conceptually). Once you release the copy, you're saying you don't want to own it anymore. But you DO want to own your own instance variable, right? So you wouldn't release it in your setter any more than you would do `name = [[newName retain] release]`.
Chuck
+1  A: 

Your first sample is correct:

- (void)setName:(NSString *)newName{
    if(name != newName) {
        [name release];
        name = [newName copy];
    }
}

but as you suspect, the copy must be balanced with a release. Assuming name has the usual semantics (i.e. you want it to stay around until the instance of the containing class is deallocated), the balancing release should come in dealloc (assuming you're not using Garbage Collection):

- (void)dealloc {
    [name release];
    //release other instance variables of type id

    [super dealloc];
}

Re-read the Memory Management Programming Guide for Cocoa if you're still confused.

Barry Wark
This is sort of where I have been going, my issue is that if I alloc my object in main (rc=1) I then pass it to my setName method and I do a copy (rc=2) I then do a release in my dealloc (rc=1) its still there?
fuzzygoat
The copy method returns a *new* instance with a retain count of 1. It does not modify the retain count of the instance that was copied.
Barry Wark
+4  A: 

In my setter I have a incoming string that I am copying to avoid any trouble should the original be modified.

- (void)setName:(NSString *)newName{
  if(name != newName) {
   [name release];
   name = [newName copy];
  }
}

My question is: as I am doing a copy where should I release it, or do I just do an autorelease? i.e.

- (void)setName:(NSString *)newName{
  if(name != newName) {
   [name release];
   name = [[newName copy] autorelease];
  }
}

As I said on your other question, autorelease translates to “send yourself release later”. That means that it counts as a release.

So, your second example releases the old value of name (good), then makes a copy of the new one (good), then puts the new one in line to be released (bad), then puts this now-doomed object into the instance variable (really bad).

The first example is correct, because you still hold a retention on the object after you put it in the instance variable.

As I also said on your other question, I think you should review the memory-management rules.

Peter Hosey
+1  A: 

Your first example is correct. So is Peter Hosey – you should better familiarise yourself with the memory management rules.

If it helps, my preferred approach as it looks a little cleaner:

- (void)setName:(NSString *)name
{
  name = [name copy];
  [_name release];
  _name = name;
}
Mike Abdullah