4

I want to make sure I understand the memory management correctly here. Is there any particular reason to use one of the assignCurrentDate methods over another here? Also, all of these result in no memory leaks, correct?

in the .h we have:

NSDate *currentDate1;
NSDate *currentDate2;
NSDate *currentDate3;
NSDate *currentDate3; 
//and 
@property (nonatomic, retain) NSDate *currentDate1;
@property (nonatomic, retain) NSDate *currentDate2;
@property (nonatomic, retain) NSDate *currentDate3;
@property (nonatomic, retain) NSDate *currentDate4;

in the .m:

-(void) assignCurrentDate1
{
currentDate1 = [[NSDate date]retain];
//[NSDate date] is autoreleased
}

-(void) assignCurrentDate2
{
currentDate2 = [[NSDate date]copy]; 
}

-(void) assignCurrentDate3
{
self.currentDate3 = [NSDate date];
}

-(void) assignCurrentDate4
{
currentDate4 = [[NSDate alloc]init];
//[[NSDate alloc]init] is not autoreleased.
}

-(IBAction) printDate
{
NSLog ("%@", currentDate1);
NSLog ("%@", currentDate2);
NSLog ("%@", currentDate3);
NSLog ("%@", currentDate4);
}

- (void)dealloc
{
[currentDate1 release];
[currentDate2 release];
[currentDate3 release];
[currentDate4 release];
[super dealloc];
}
Cephi
  • 221
  • 2
  • 10
  • 2
    Related: [When to use retain and when to use copy](http://stackoverflow.com/questions/4087208/when-to-use-retain-and-when-to-use-copy) – PengOne Jun 20 '11 at 20:23

2 Answers2

6

The rule of thumb when it comes to iOS memory management is:

For every alloc, retain, copy, or new, you must have a corresponding release or autorelease.

You are leaking in several places actually. In your header, you retain your date objects and then in your dealloc method you release them. That is correct. However, In your assignDate methods, you fail to release the copy or retained date. While [NSDate date] is autoreleased, you are retaining and copying them yourself.

There is no reason to use your assignCurrentDate methods. You can just do something like the following in your init method:

self.currentDate1 = [NSDate date];

That's it.

Edit: (Okay, that's not it.)

As Jim points out in the comments:

The retain in the header signifies that the synthesized setter for those properties will retain objects assigned to them. But if you look at the assign* methods, you'll see that only assignCurrentDate3 actually uses the property. The rest assign directly to the ivar, bypassing the synthesized setter, so they aren't retained upon assignment.

Moshe
  • 57,511
  • 78
  • 272
  • 425
  • 4
    just to add as info: the leaking happens if you call `assignCurrentDate1/2/4`. Only `assignCurrentDate3` is safe, as it calls the setter of the property which will release the stored value and retain the new value given. – marcus Jun 20 '11 at 20:28
  • 1
    That's not correct at all. *"In your header, you retain your date objects"* - Nothing is being retained in the header. Those are property declarations. The `retain` in the header signifies that the synthesized setter for those properties will retain objects assigned to them. But if you look at the `assign*` methods, you'll see that only `assignCurrentDate3` actually uses the property. The rest assign directly to the ivar, bypassing the synthesized setter, so they aren't retained upon assignment. – Jim Jun 20 '11 at 20:35
  • 1
    `assignCurrentDate1/2/4` methods fail to release the old value before assigning the new one. They will **leak** if they are called more than once. The new values are retained properly in all cases. – albertamg Jun 20 '11 at 20:49
  • Yes, *if used more than once*. This is sample code contrasting different ways of creating and assigning objects - it seems to me that the separate methods were just used as a way of separating the different cases, as they are pretty pointless as-is. Sure, if you're assuming that what is in question here are the methods as a whole, you don't want to do it that way, but I didn't get that impression - who writes a method just to assign an object? – Jim Jun 20 '11 at 20:58
  • @Moshe Awesome answers all, thanks. So put another way: 1, 2, and 4 are not retained by the setter but they do have their retain counts incremented because of the retain, copy, and inits used. If new date objects are later assigned to these ivars the old objects lose their pointer and are never released (causing a leak). – Cephi Jun 20 '11 at 22:34
  • @Cephi - Sound right. (@Jim, feel free to correct me, if I'm wrong. :-D) – Moshe Jun 20 '11 at 22:37
2

Yes, you understand memory management correctly. None of those leak, assuming you don't call the methods more than once. The second is less efficient in terms of memory use as two instances of NSDate are created. In fact, they all slightly vary performance-wise, but not in a significant way unless you are putting them into tight loops.

In terms of program design, you wouldn't want to write code like this because if you ever call 1, 2 or 4 more than once, the originally allocated instance will leak. If you're sure that this isn't a problem (e.g. if you assign in viewDidLoad and release in viewDidUnload), then you are safe using any of those styles, but if you aren't sure that this is the case, you either need to guard your assignment by releasing before assigning, or you should use the third property-based method, which does this for you.

Jim
  • 72,985
  • 14
  • 101
  • 108