NSDate init question, related to memory management in Objective-C - objective-c

I have an NSDate object created by
NSDate *date = [[NSDate alloc] init];
Later, I want to reset the date to the "now", so I thought that
[date init];
or
date = [date init];
might do the job, but they don't. Instead,
[date release];
date = [[NSDate alloc] init];
works. I'm a bit confused about this, since in the documentation for - (id) init, it says:
Returns an NSDate object initialized to the current date and time.
and since date is already allocated, shouldn't it just need an init message?

Think of alloc and init as logically inseparable halves of a constructor. You can only call methods beginning with "init" once on a given object — once the object has been initialized, and it's an error to initialize it again. This is true for any Objective-C object, not just NSDate. However, NSDate objects are also immutable — once created, they can't change.
The reason the latter code works is because you're creating a new instance of NSDate, which is the correct thing to do. You can also use [NSDate date] to accomplish the same thing. Be aware that it returns an object that you don't (yet) own, so you'll need to retain it if you need to keep it around, and release it later.
Be aware that if you receive an object from someone, it has already been initialized. (If not, it's a programming error in the code that provided it, or is an extremely uncommon exception to the rule.)

If you want to get the current date you can just use:
NSDate * now = [NSDate date];
If you want to keep it then retain it.
NSDate * now = [[NSDate date] retain];
You can't reset NSDate with init, init is only for initializing the object for the first time.
You could just get another date:
NSDate * now = [[NSDate date] retain];
// use the now object
// need new date
[release now];
now = [[NSDate date] retain];
// once you don't need it release it
[now release];
The date message returns autoreleased instance of NSDate, hence the release or autorelease.
The autorelease is used for cases where you don't want to worry about where exactly you need to release the object - it is put into autorelease pool. Object in autorelease pool are released after the end of event loop iteration, or when you call release on pool ... (see more in Apple docs about memory management).
Btw. the [NSDate date] is a convenience method it's probably something like (not quaranteed to be exactly the same but functionally similar to):
- (NSDate *)date
{
return [[[NSDate alloc] init] autorelease];
}

Related

potential leak value stored never read in NSMutableArray

NOTE: i want to alloc my NSMutableArray and then assign data in it.
i got leak in below code
NSMutableArray *responseArr=[[NSMutableArray alloc]init];
responseArr =[response valueForKey:#"result"];
Also in here value stored never read
NSString *name=_txt_name.text;
if ([name length]==0) {
name=#"";
}
Also leak in below
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd/MM/yyyy HH:mm:ss"];
//below here i get leak
NSDate *dateStart = [[NSDate alloc] init];
dateStart = [dateFormatter dateFromString:startDate];
EDIT :
I have disable ARC using -fno-objc-arc in reachability Class even i get below leaks
This line
NSMutableArray *responseArr=[[NSMutableArray alloc]init];
Allocates a new NSMutableArray and assigns a reference to it to responseArr
This line
responseArr = [response valueForKey:#"result"];
Takes a value from a dictionary (that presumably is a reference to an NSMutableArray) and assigns that to responseArr. At this point there are no more references to the original NSMutableArray that you allocated, so it will be deallocated.
You can just say:
NSMutableArray *responseArr = (NSMutableArray *)response[#"result"];
Similarly with your date code, you could just say:
NSDate *dateStart = [dateFormatter dateFromString:startDate];
There is no need to assign an initial value, only to throw it away.
None of the code you have shown will cause leaks, assuming you are using ARC.
If you aren't using ARC, then start using ARC!
A. First snippet
Using MRC (MRR) you have to balance allocations with +alloc your own:
NSMutableArray *responseArr = [[NSMutableArray alloc]init];
responseArr = [response valueForKey:#"result"];
In the first line you allocate an instance of NSArray. You have to (auto-)release it later, otherwise it is a memory leak. I think you misunderstood that you create a new instance of NSArray using -valueForKey and assign the value of this new reference to responseArr. (Therefore you do not need a mutable array.) After that you created two objects having only one reference to the new one, you can never release the old one.
Do something like this:
NSArray *responseArr = [[NSArray alloc]init];
NSArray *resultArr =[response valueForKey:#"result"];
[responseArr release];
You do not have to do that with the object referred by resultArr, because it isn't created with +alloc-init. Here you get an introduction to ownership.
B. Third snippet
It is the same with the last example:
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
You +alloc-init that instance object, but there is no release in your code. Therefore it cannot be released anymore, when the reference dateFormatter loses its extent (lifetime), i. e. returning from the method.
Add this code at the end of the method:
[dateFormatter release];
C. Second snippet
The second example has a different problem: You assign a value to the var name without using the variable in the code below. So assigning the value is meaningless.

Objective C programming, passing message to NSDate

I am following a book for objective-C and came across this example to print the current date using NSLog statement. I am confused why the NSDate class was not instantiated(alloc and init) before passing the date message to it.
NSDate * pointerToIt = [NSDate date];
Further down the code another message was passed to this pointer..
[pointerToIt timeIntervalSince1970];
What I knew is as long as the pointer holds the address to instance of a class messages can be sent to it but the class was never instantiated and still the messages are being passed. Can someone throw some light on this for me ?
The date is a somewhat special way to get the current date. It is a static method on the NSDate class which does the following:
Creates and returns a new date set to the current date and time.
This method uses the default initializer method for the class, init.
Your code is pretty much the same as in the docs:
NSDate *today = [NSDate date];
Therefore the today object is in fact implicitly correctly initalized.
[NSDate date] did the alloc and init for you. If you refer to the documentation you will read.
Creates and returns a new date set to the current date and time.
[NSDate date] is a class factory method. Internally, it would look something like this:
+ (instancetype)date {
return [[self alloc] init];
}

initialize an instance in objective-C with alloc and init

I am learning Objective-C and I've just read about alloc and int methods. Before this point,when I wanted to create an instance of NSDate for example, I coded:
NSDate *now = [NSDate date];
Now I saw that the above can be written like this
NSDate *now = [[NSDate alloc] init];
Are the above do the same thing? As i have understood (hopefully correct) the first one creates and instance of NSDate, by sending the message date to the class NSDate. The second one, it just allocates space for the instance and initialize it, so that it is ready to work.
You would think the two things you list were definitely not the same thing based on a background knowledge of Objective-C, if you weren't familiar with NSDate. But in fact, they are the same thing in this case.
[NSDate date] is calling an NSDate class method that returns an NSDate object set to the current date and time.
Normally, a method call like [[NSDate alloc] init] would instantiate a new default object of the type requested, so you might expect that this would not be set to any date/time. However, the default NSDate object is in fact initialised with the current date and time, as discussed in the documentation, so in this particular case—they are the same thing.
As an aside, as with most NSObjects, you can also just call [NSDate new] to get the same effect as [[NSDate alloc] init] (and thus the same effect in this case as [NSDate date]).

NSDate - How does the default initializer allocate space on the heap?

I know it's good practice to explicitly alloc and init objects, but I'm confused why it is not needed for instances of NSDate in the following example:
NSDate *now = [NSDate date];
Appears to be the same as this...
NSDate *now = [[NSDate alloc] init];
I assume the date class method allocates space on the heap, but I have only found NSDate.h and not how Apple actually implemented the method.
Apple documentation simply says, "This method uses the default initializer method for the class, init."
+[NSDate date] is a "convenience constructor". Typically the implementation will look very similar to return [[[self alloc] init] autorelease].

Copying NSDate objects and releasing

if I do this:
NSDate *dateStart;
[dateStart alloc];
// Initialise with a date somewhere here..
..
// Modify the start date.
dateStart = [chosenDate copy];
Should I be doing a [dateStart release] before assigning the dateStart pointer?
I'm from a C/C++ background and I don't understand the whole ObjectiveC/iOS garbage collection behaviour (if indeed there is any). My C background is telling me I should be freeing the initial NSDate object that dateStart is pointing to. Would that be correct?
Yes since you allocated it before you should release it before this line
//Release it before reassign
[dateStart release];
dateStart = [chosenDate copy];
Also notice that its preferred that you do the allocation and initialization on the same line, dont break them to multiple lines
So this
NSDate *dateStart;
[dateStart alloc];
Would change to
NSDate *dateStart = [[dateStart alloc] init....];