Releasing objects: [obj release]; is not enough, need [obj release], obj = nil;? - objective-c

Here I got some ugly code:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy"];
NSDate *date = [NSDate date];
NSString *textWithYear = [NSString stringWithFormat:#"text and year %#", [dateFormatter stringFromDate:date] ];
[dateFormatter release];
NSLog(#"%i", [dateFormatter retainCount]); // returns 1 !
As you see, retains counter returns 1, which I suppose means that the object is not released.
If I change that string to
[dateFormatter release], dateFromatter = nil;
retains counter returns 0, which is supposedly because it can't count retains for nil :)
Is there something that I don't understand about retains counter, or this object is really not released? When I send release to it for the second time (striving to get zero retains count) it crushes expectedly :)
And one more question: if the dateFormatter was really released, why doesn't it crash when i call [dateFormatter retainCount] ?

You are correctly releasing your object; don't worry about the retain count. And don't use -retainCount. See When to use -retainCount? or Calling -retainCount Considered Harmful for more details about why.
Do note that your code here will crash if the object does get destroyed (because the call to -retainCount comes after you've released it and may be to a dangling pointer); setting your variables to nil after you are done with them is a good habit to protect against this. But it has nothing to do with whether your code is leaking.

Related

how to use nsdate string objec for later use?

I'm so fedup with NSDate string object.
currently I am generating an unique id on the bases of NSDate as follows:
NSDate *current_date = [[NSDate date]retain];
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"HHmmssddMMYY"];
NSString *unique_id=[df stringFromDate:current_date];
NSString * current_Test_id=[NSString stringWithString:unique_id];
NSLog(#"current_test_idString %#",current_Test_id);
The code above is generating unique id and prints successfully but if I am printing or accessing currtent_Test_id in another IBAction method then app crashes.
stringWithString will create an autorelease string, modify your code as
NSString * current_Test_id = [[NSString stringWithString:unique_id]retain];
Use this Method
- (NSString *)stringDateFromDate: (NSDate *) date{
NSDateFormatter *df = [[NSDateFormatter alloc]init];
[df setDateFormat:#"HHmmssddMMYY"];
NSString *current_Test_id=[NSString stringWithString:[df stringFromDate:date]];
[df release];
NSLog(#"current_tst_id %#",current_Test_id);
return current_Test_id;
}
Call Method Like that
NSString *current_tst_id = [self stringDateFromDate:[NSDate date]];
an NSString (or any object, for that matter) created with a class method, and not an init method, will be autoreleased. This means on the next iteration of the event loop, current_Test_id is released, and now you have a pointer to a dead object.
See this similar question
As current_Test_id is instance method.
in the init (in case of mac os) or viewDidLoad (for ios) alloc+init it.
and then assign :
current_Test_id=[NSString stringWithString:unique_id]; //it will be in autorelease mode.
or
current_Test_id=[[NSString stringWithString:unique_id]retain];

Releasing an NSString that I am done with causes a crash

Note the commented-out [printvolfirst release]; line below. If I un-comment it, the program crashes. I can't figure out why. The printvolfirst variable is not used anywhere else except in the lines of code you see here. After it is assigned to printvol I'm done with it. So why not release it?
vol = vol / 1000000;
NSNumberFormatter * format = [[NSNumberFormatter alloc] init] ;
[format setPositiveFormat:#"#.#"];
NSString * printvolfirst = [[NSString alloc]init];
printvolfirst = [format stringFromNumber:[NSNumber numberWithFloat:vol]];
NSString * printvol = [[NSString alloc] initWithFormat: #"%#M", printvolfirst];
self.Pop.vol.text = printvol;
[printvol release];
//[printvolfirst release];
[format release];
stringFromNumber: autoreleases the returned object. If you release it again, it's released after it has been deallocated.
In fact, you don't even need this code:
NSString*printvolfirst=[[NSString alloc]init];
You can turn on 'Run Static Analyser' in the build settings to get warned about such things.
You are deallocating an autoreleased string. Although you are doing NSString*printvolfirst=[[NSString alloc]init];, you are losing the reference to that object when you do printvolfirst=[format stringFromNumber:[NSNumber numberWithFloat:vol]]; where you assign an autoreleased object to printvolfirst. In the process, you have also created a memory leak. You don't have to release it.

Getting date info into an array in Objective-C Cocoa framework

I have a function that returns an array to hold date info.
- (NSArray*) getTodayArray
{
NSDate *today = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYY"];
NSString *year = [dateFormatter stringFromDate:today];
[dateFormatter setDateFormat:#"MM"];
NSString *month = [dateFormatter stringFromDate:today];
[dateFormatter release];
NSArray *res = [NSArray arrayWithObjects: year, month, nil];
return res;
}
Q1 : Is there any easy way to get all the info (year, month, date, hour, minute ...) in an array not using setDateFormat over and over again?
Q2 : Is there a way so that I can access the content of array using res['year'] or similar? I mean using dictionary?
Q3 : Do I need to release NSArray *res in the caller of this function?
A1: You can do smth like this:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYY|MM"];
NSArray* d_arr = [[dateFormatter stringFromDate: [NSDate date]] componentsSeparatedByString: #"|"];
A2: Use NSDictionary:
[NSDictionary dictionaryWithObjectsAndKeys: [d_arr objectAtIndex: 0], #"year", [d_arr objectAtIndex: 1], #"month", nil]
A3: return value is autoreleased. you don't need to release it.
#prosseek
1 - I dont think you have another choice to get the year, month, date, hour, minute ... from NSDate other than this.(I am not sure about it though.)
2 - you can access the objects in the dictionary in the above format but something more like objective-c style. like this
[dateDictionary obectForKey:#"year"];
but you need to define the dictionary in that format
like this
NSDictionary *dateDictionary = [NSDictionary dictionaryWithObjects:year,min,hr,nil forKeys:#"year", #"min", #"hour", nil];
3 - no you dont need to release or autorelease the NSArray in the above method . but i think you need to retain it in the array that is receiving res array if you want to use it after a while.
Why don't you just use a NSArray of NSDates?
You can probably get all of your desired functionality out of its plethora of functions.
A1: You could dump it all out into a string, but then you'd have to parse the string, which wouldn't be any easier.
A2: You could do that if you used an NSDictionary instead of an NSArray.*
A3: No, it's already autoreleased.
* Why don't you write a category for NSDate instead?
NSDate+Convenience.h
#interface NSDate (Convenience)
- (NSInteger)year;
- (NSInteger)month;
#end
NSDate+Convenience.m
#implementation NSDate (Convenience)
- (NSInteger)year {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"YYYY"];
NSString *myYear = [dateFormatter stringFromDate:self];
[dateFormatter release];
return myYear;
}
- (NSInteger)month {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"MM"];
NSString *myMonth = [dateFormatter stringFromDate:self];
[dateFormatter release];
return myMonth;
}
#end
Just #include NSDate+Convenience.h wherever you want to use your handy date and month accessors. All of your NSDate instances will then get them:
NSDate *myDate = [NSDate date];
NSLog(#"%ld %ld", [myDate year], [myDate month]);
No need for loosely-typed NSArrays or NSDictionaries to store this stuff.
(Note you could modify the above code to use a shared NSDateFormatter.)
Q1: Not an array, but you can use -[NSCalendar components:fromDate:] to get an NSDateComponents object. You can use it directly or build an array from it, if that is your preference.
Q2: No, but if you return an NSDateComponents object, then you can use -year, -month, etc methods on it.
Q3: No, you don't need to release it in this method or the caller, unless the caller retains it (which may be desirable).
You're looking for the NSDateComponents class. You'll need to create an NSCalendar object first, then call the components:fromDate: method to get the DateComponents object, after which you can access the object's month, year etc. properties.
Not quite sure what you want here. As it stands, the array cannot be accessed in the manner you describe, though if you want you could always create a dictionary and assign values for keys such as 'month' or 'year'. However, it might just be easier to return the DateComponents object, and access its properties.
No, there is no need to release the NSArray. You constructed it using the NSArray class method, which is already autoreleased.

Objective-C : memory leak or not with multiple assignation with autorelease?

If I do the following thing, will this make memory leaks ?
SomeClass* tmp;
NSDate* thetmpdate;
tmp = [[[SomeClass alloc] init] autorelease];
thetmpdate = [NSDate date];
// Do something long with tmp and date
tmp = [[[SomeClass alloc] init] autorelease];
thetmpdate = [NSDate date];
// Do something long with tmp and date
tmp = [[[SomeClass alloc] init] autorelease];
thetmpdate = [NSDate date];
// Do something long with tmp and date
No, there's no leak in the code you posted.
All objects will be autoreleased when the autorelease pool is flushed, no matter if the variable holding their pointers is changed or not.

Date formatter memory leak

Hey, I've been wokring through my app and removing the memory leaks but the below one has me beaten, any help would be much appreciated.
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
[dateFormatter setDateFormat:#"dd/MM/yyyy"];
claim.date = [dateFormatter dateFromString:[data objectForKey:key]];
[dateFormatter release];
The date property is defined as:
#property (nonatomic, retain) NSDate *date
Thanks
Edit:
Forgot to mention where the memory leak occurred, its on line claim.date = [dateFormatter dateFromString:[data objectForKey:key]];
I suspect one or both of the following:
The owner of claim never released it
The implementation of claim does not send the release message to date in its dealloc and/or does not self.date = nil in the viewDidUnload.