PDA

View Full Version : Do you need to alloc / init every instance of NSDate (or any class)




animefx
Dec 4, 2011, 09:28 PM
I'm starting to learn about objects in Obj-C and have been messing around with NSDate class. I'm a little confused if I need to alloc / init every instance of say, NSDate I would create. Also, if I had to alloc / init this line of code:

NSDate *myDateMuchMuchLater = [myDate dateByAddingTimeInterval:(NSTimeInterval)89500000];

... I'm not ever sure how I would do it.

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

// insert code here...
NSDate *myDate = [[NSDate alloc] init];
NSLog(@"The current date is %@", myDate);

NSDate *myDateMuchMuchLater = [myDate dateByAddingTimeInterval:(NSTimeInterval)89500000];
NSLog(@"The current date with 89,500,000 seconds added is %@",myDateMuchMuchLater);


[pool drain];
return 0;
}



Sydde
Dec 4, 2011, 09:48 PM
If you are using XCode, open Documentation from the Help menu and locate the Cocoa Memory Management guide. There is a specific policy relating to the creation of objects and how long you want them to live that you really should become familiar with. This can be challenging stuff, even seasoned programmers trip over it. At least try to understand the difference between what the initWith... instance method returns as opposed to the class method (like dateWith... in this case).

Senor Cuete
Dec 5, 2011, 07:58 AM
Your code won't release it because you didn't put it in the autorelease pool. You would need to [object autoRelease] it to get it deallocated by calling [pool drain]. If you create an object by allocating it you need to see that it's deallocated.

whooleytoo
Dec 5, 2011, 09:30 AM
Using alloc creates 'permanent' objects, objects that will remain allocated until you release them. On the other hand, using methods like "dateBy...", or "stringWith..." creates 'temporary' objects which are likely to be released once out of the current scope. If you wish to use them beyond the current scope, you need to retain (and later, release) them.

You can probably use them interchangeably, which you use tends to be a matter of whether you're creating a NSDate/NSString etc. for temporary use in a method, or assigning it to an object's instance variable for later use.

As a rough rule of thumb for Cocoa memory management, you need to balance the methods you call:

These increase the retain count:
- alloc
- retain
- copy

- These decrease the retain count:
- release
- autorelease

For each method call from the first group, one of the methods of the second group needs to be called, or your code will leak. OTOH, if you call methods from the second group, without previously calling a method from the first, your code will probably crash.

chown33
Dec 5, 2011, 11:30 AM
As a rough rule of thumb for Cocoa memory management, ..

If you know what ownership means, all you have to remember is the naming of methods that return owned objects. The actual ownership rule is simple enough, you shouldn't need a rule of thumb.
http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/MemoryMgmt/

Look under "Basic Memory Management Rules".

animefx
Dec 5, 2011, 02:12 PM
I don't think you guys are understanding my question. Let me rephrase it... How do you know when you need to own an object?

If I can create NSDate's with and without owning it several times in my code then how do you know which one to do?

Senor Cuete
Dec 5, 2011, 02:23 PM
Typically the main function in a Mac app looks like this:

int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **) argv);
}

NSApplicationMain() creates an auto release pool that is drained on each trip through the event driven loop so you don't have to allocate one.

whooleytoo
Dec 5, 2011, 02:23 PM
If you know what ownership means, all you have to remember is the naming of methods that return owned objects. The actual ownership rule is simple enough, you shouldn't need a rule of thumb.
http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/MemoryMgmt/

Look under "Basic Memory Management Rules".

Viewing/wording the memory model as I did in my post helped me understand it; better than Apple's documentation. So I posted it in case it might help the OP understand.

I don't think you guys are understanding my question. Let me rephrase it... How do you know when you need to own an object?

If I can create NSDate's with and without owning it several times in my code then how do you know which one to do?

As in my post above, if you call alloc, retain or copy methods, you take ownership and are responsible for later releasing that object (via release or autorelease). If you're not calling them, you don't have ownership.

chown33
Dec 5, 2011, 02:54 PM
I don't think you guys are understanding my question. Let me rephrase it... How do you know when you need to own an object?

If I can create NSDate's with and without owning it several times in my code then how do you know which one to do?

Ownership is associated with ongoing use of an object. If your use is not ongoing, then autorelease may be ok (it depends on autorelease pool draining). If your use is ongoing, then ownership is required. As soon as you no longer need ongoing use of the object, you relinquish ownership.

Look at it this way: if you don't have ownership, then the object might go away spontaneously, at some unspecified time in the near future. "Unspecified" really means "at the next autorelease pool drain".

You need ownership of an object when you need control of its lifetime, which means its existence as a valid object. If you don't know what object lifetime is or its significance, then you really need to look at the memory management guide I previously linked. It has diagrams and descriptions.

animefx
Dec 5, 2011, 02:56 PM
Thanks for your replies (and everyone else too) I really appreciate it! I hope no one is frustrated by my questions. I understand that when I alloc, retain, or copy aka ARC, that it's my responsibility to pair them with a release or use the auto release pool. My question is when do I know if I *need* to alloc and init an object to begin with

meaning I've seen code where they created a pointer to NSDate and did NOT release it themselves or use autorelease... this is in the big nerd ranch's book. and other times they did alloc and init NSDate.

example:
NSDate *myDate = [NSDate date];

other times I've seen it as:
NSDate *myDate = [NSDate alloc] init];

Is there a good reason they did not alloc / init NSDate in the first example?

once again I understand why I need to release it and how, I'm wondering when an object *needs* to be alloc and init. the way the book sounded is that you always needed to do this, but I've seen a lot of code with objects that have no been allocated / init (or used NEW)

I have a feeling someone will say, well those are temporary... well, how do you determine what temporary is? I could alloc init every single object I create but if its using up more memory on the heap than it needs to my program is going to be a memory hog, and or slow.

Viewing/wording the memory model as I did in my post helped me understand it; better than Apple's documentation. So I posted it in case it might help the OP understand.



As in my post above, if you call alloc, retain or copy methods, you take ownership and are responsible for later releasing that object (via release or autorelease). If you're not calling them, you don't have ownership.

Sydde
Dec 5, 2011, 03:27 PM
Typically, when any given method is called, it will be within the logical bracket of some autorelease pool, such as one iteration of a run loop. Objects that are solely on the stack (method declared variables) will not usually live beyond the current pass of the run loop, so they should be disposed of appropriately (not allowed to cause a memory leak). All other objects (statics, globals, ivars) usually live longer than one pass, so they will probably need to be retained, though it is helpful to understand the difference between strong and weak references (who the actual owner of an object should be).

If you can build with ARC, these issues will mostly be handled for you (once you know how to set up properties). GC can also take care of memory management, but it is a bit more of a performance hit (especially memory footprint) than manual or automatic reference counting.

animefx
Dec 5, 2011, 04:30 PM
Thank you, this explains a lot.

I haven't used the debugger much but is there a way to step through my program to make sure all of my retain counts on objects are 0 just before the program ends?

Typically, when any given method is called, it will be within the logical bracket of some autorelease pool, such as one iteration of a run loop. Objects that are solely on the stack (method declared variables) will not usually live beyond the current pass of the run loop, so they should be disposed of appropriately (not allowed to cause a memory leak). All other objects (statics, globals, ivars) usually live longer than one pass, so they will probably need to be retained, though it is helpful to understand the difference between strong and weak references (who the actual owner of an object should be).

If you can build with ARC, these issues will mostly be handled for you (once you know how to set up properties). GC can also take care of memory management, but it is a bit more of a performance hit (especially memory footprint) than manual or automatic reference counting.

gnasher729
Dec 5, 2011, 05:19 PM
Thank you, this explains a lot.

I haven't used the debugger much but is there a way to step through my program to make sure all of my retain counts on objects are 0 just before the program ends?

Use "Analyze" in XCode. Best to set up your project to always start the static analyzer when you build, and to treat all Analyze problems as errors.

Sydde
Dec 5, 2011, 10:16 PM
Thank you, this explains a lot.

I haven't used the debugger much but is there a way to step through my program to make sure all of my retain counts on objects are 0 just before the program ends?

Retain counts cannot ever be observed to be 0. If you have actually released an object, the dangling pointer will either be invalid or will point to a different object. You may be able to see a retain count of 1 right before you send -release to an object, but you should not rely on a retain count to be meaningful. You could, I suppose, write a subclass for the objects you are concerned about, with a NSLog(@"%@ released", self); right before [super dealloc]; but this can be challenging with some classes, such as NSString.

It is good, I think, that you are concerned about proper memory handling, in the sense that your code might be converted into a framework or some kind of component or plugin, but remember, programs themselves operate within a sort of memory zone that is unique to the run and just gets zapped at the end: you cannot have a leak that persists beyond where main() exits.