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

Discussion in 'Mac Programming' started by animefx, Dec 4, 2011.

  1. macrumors regular

    Joined:
    May 10, 2005
    Location:
    Illinois
    #1
    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:

    Code:
    NSDate *myDateMuchMuchLater = [myDate dateByAddingTimeInterval:(NSTimeInterval)89500000];
    ... I'm not ever sure how I would do it.

    Code:
    #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;
    }
     
  2. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #2
    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).
     
  3. macrumors regular

    Joined:
    Nov 9, 2011
    #3
    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.
     
  4. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #4
    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.
     
  5. macrumors 603

    Joined:
    Aug 9, 2009
    #5
  6. thread starter macrumors regular

    Joined:
    May 10, 2005
    Location:
    Illinois
    #6
    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?
     
  7. macrumors regular

    Joined:
    Nov 9, 2011
    #7
    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.
     
  8. macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #8
    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.
     
  9. macrumors 603

    Joined:
    Aug 9, 2009
    #9
    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.
     
  10. thread starter macrumors regular

    Joined:
    May 10, 2005
    Location:
    Illinois
    #10
    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.

     
  11. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #11
    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.
     
  12. thread starter macrumors regular

    Joined:
    May 10, 2005
    Location:
    Illinois
    #12
    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?

     
  13. macrumors G5

    gnasher729

    Joined:
    Nov 25, 2005
    #13
    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.
     
  14. Sydde, Dec 5, 2011
    Last edited: Dec 5, 2011

    macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #14
    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.
     

Share This Page