Retain/copy of autoreleased objects - iphone

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];
}

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.

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.

Related

Clarification Needed Regarding retainCount [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
NSString retainCount is 2147483647
Let say i have an class named as MyTestClass.h.
There are three NSString variables which are initialized different ways
Class structure is look like
#interface MyTestClass : NSObject {
NSString *testString1;
NSString *testString2;
NSString *testString3;
}
#property (nonatomic, retain) NSString *testString1;
#property (nonatomic, retain) NSString *testString2;
#property (nonatomic, retain) NSString *testString3;
#end
MyTestClass.m
#implementation MyTestClass
#synthesize testString1, testString2, testString3;
-(id) init{
self.testString1 = #"";
[self setTestString2:#""];
testString3 = #"";
}
Now i am planning to create an object of MyTestClass
MyTestClass *obj = [[MyTestClass alloc] init];
I think after this code line execution testString1, testString2 and testString3 retainCounts will be 1.
Am i correct my friends?
may i know that what will happened if i release testString3 ?
Any help on this is appreciated.
Thanks
Since you are using literal strings in this example retainCount is of no importance (not even as a delta) since those string objects aren't actually ever going to be dealloc'd.
However, if you were assigning a runtime allocated string to each of your properties, the first two would be retained, the third would not. Since your properties are declared as retain and you're using dot syntax in one and the "setProperty" syntax in the other, the same setter is executed and the object passed to that setter is retained. The third example you're simply setting the backing ivar for the property to the value on the right and not affecting it's ownership.
It's worth noting, retainCount is only ever useful as a delta and shouldn't be thought of as an explicit number. You should never explicitly check the value of retainCount, since it's absolute value is unpredictable and of no use. You seem to understand this in your question, but it's worth restating whenever dealing with retainCount to make sure all involved understand it.

Am I leaking this ObjectiveC Object?

#interface foo: NSObject
#property (nonatomic, retain) NSMutableArray *aMutableArray;
#end
#implementation
#synthesize aMutableArray
-(void)somefunction {
// Illustration
self.aMutableArray = [[[NSMutableArray alloc]init]autorelease];
self.aMutableArray = [[[NSMutableArray alloc]init]autorelease];
self.aMutableArray = [[[NSMutableArray alloc]init]autorelease];
}
#end
I have done code similar code to this in other parts of my program, but I needed to be certain that this does not cause a memory leak. With my understanding of autorelease, this object is released correctly right?
[EDIT - added question]
One question though: the property above has a retain attribute, so when the compiler creates the setter function, the setter code will look something like this:
somecode..
retain newObj
release oldObj
somecode..
in the code above, I assigned 3 objects to aMutableArray.
Each time they are assigned, the setter function did a retain on the newObj and a release on the oldObj. So, since the setter method already did a release, will there be a problem when the autorelease kicks-in to release the object a second time?
Yes, it will be released correctly if you also release it dealloc method:
- (void) dealloc{
[aMutableArray release];
[super dealloc];
}
Note also that you can shorten your code using equivalent convenience +array method of NSMutableArray:
self.aMutableArray = [NSMutableArray array];

iPhone SDK: Memory leak in assiging property values?

I have a leakage in my connectionDidFinishLoading class how can fix this?
#property (nonatomic,retain) NSMutableData *responseXMLData;
#property (nonatomic,copy) NSMutableData *lastLoadedResponseXMLData;
-(void)dealloc {
[responseXMLData release] ;
responseXMLData=nil;
[lastLoadedResponseXMLData release];
lastLoadedResponseXMLData=nil;
[super dealloc];
}
#property (nonatomic,copy) NSMutableData *lastLoadedResponseXMLData;
Since you are working with a mutable object that you are going to be setting and changing, you should use RETAIN:
#property (nonatomic,retain) NSMutableData *lastLoadedResponseXMLData;
retain - "Specifies that retain should be invoked on the object upon assignment. ... The previous value is sent a release message." So you can imagine assigning an NSString instance (which is an object and which you probably want to retain).
copy - "Specifies that a copy of the object should be used for assignment. ... The previous value is sent a release message." Basically same as retain, but sending -copy rather than -retain.
Here is some good reading on the various get/set methods you can instruct #property/#synthesize to create for you: http://cocoawithlove.com/2010/06/assign-retain-copy-pitfalls-in-obj-c.html
you did not tell us where you are creating the object for responseXMLData? where ever you are initializing that object should release that
self.responseXMLData = [[NSMutuableData alloc]init]autorelease];
and in your dealloc method you could have just say
-(void)dealloc {
self.responseXMLData = nil; //which is equivalent to [responseXMLData release]; responseXMLData=nil;
}
and
Just a thought, in your:
self.lastLoadedResponseXMLData = nil;
self.lastLoadedResponseXMLData = self.responseXMLData;
Before one release happens at dealloc, could there be a possible where your just set to nil and copy next responseXMLData to lastLoadedResponseXMLData without releasing any previous copies?

is this line of code correct re memory management (re NSDate copy)?

is this line of code correct re memory management (re NSDate copy)?
I have a class with properties:
#property (nonatomic, retain) NSDate* start;
#property (nonatomic, retain) NSDate* coreWeStart;
Now in the init method, assuming self.start is already set, is this correct re setting the coreWeStart to the same date:
self.coreWeStart= [[self.start copy] autorelease];
Just double checking my understanding that:
needs a 'copy' as otherwise it would refer to the same object and
needs an autorelease as I did do a copy
thanks
I would say kind of, but it could still be done better. Specifically, you could do:
#property (nonatomic, copy) NSDate* coreWeStart;
...and then:
self.coreWeStart = self.start;
...to get the same thing with less code. Also be sure to do self.coreWeStart = nil in dealloc (and self.start = nil too).
Yep. You got it.
Copy returns a new object with a retain count of one.
assigning it to the retain keyword property will increment the retain count.
autorelease will decrement the retain count.
So your object has the coreWeStart property with a retain count of one, which is a copy of the start property.

Using NSDate as a property gives me EXC_BAD_ACCESS, why?

I am adding NSDate as a pointer with a property, and every time I unload my view, it crashes with EXC_BAD_ACCESS. I am doing (not posting full code):
.h
NSDate *scheduledDate;
#property (nonatomic, retain) NSDate *scheduledDate;
.m
#synthesize scheduledDate;
- (void)dealloc {
[super dealloc];
[asset release];
[passedDate release];
[eventDate release];
[eventName release];
}
I have not done anything else with the pointer, but I still get EXC_BAD_ACCESS. Why is this happening? Is there a different way to set the property for NSDate?
SORRY:
I fixed an error in my question code, it was only a copy and paste issue, not a fix to my problem, it still exists.
You're calling [super dealloc] before the release in your dealloc implementation. That means the [scheduledDate release] is release some non-free memory (which is no longer nil).
Specifically, change the order so [super dealloc] is last:
- (void)dealloc {
[asset release];
[passedDate release];
[eventDate release];
[eventName release];
[super dealloc];
}
Your code looks inconsistent. The #property declaration should be for "NSDate scheduledDate", not "NSString ...".
If you are not using #property (nonatomic, retain) NSDate *scheduledDate; then there is no need to synthesize scheduledDate.
Also, how are you determining the value of scheduledDate? post the code you are using for it.
Also, post the crash log that your app produces.
Your #property (nonatomic, retain) is for "passedDate", not "scheduledDate". Since "scheduledDate" is not getting instantiated and retained by #property (nonatomic, retain), then attempting to release it is attempting to release something that hasn't been created yet (it isn't being synthesized as a property).