Object Lifecycle Question

Discussion in 'Mac Programming' started by CMT, May 23, 2010.

  1. CMT macrumors regular

    CMT

    Joined:
    Aug 24, 2009
    #1
    Just a simple beginner question, what's the difference between:

    Code:
    #import <Cocoa/Cocoa.h>
    #import "ClassOne.h"
    
    
    @interface ClassTwo : NSObject {
    	
    	ClassOne *objectFromClassOne;
    }
    
    -(void)doSomething;
    
    @end
    
    @implementation ClassTwo
    
    -(void)doSomething {
    	
    	objectFromClassOne = [[ClassOne alloc] init];
    	
    	// ...
    	
    	[objectFromClassOne release];
    	
    }
    
    @end
    
    
    And:

    Code:
    
    #import <Cocoa/Cocoa.h>
    #import "ClassOne.h"
    
    
    @interface ClassTwo : NSObject {
    	
    }
    
    -(void)doSomething;
    
    @end
    
    @implementation ClassTwo
    
    -(void)doSomething {
    	
    	ClassOne *objectFromClassOne = [[ClassOne alloc] init];
    	
    	// ...
    	
    	[objectFromClassOne release];
    	
    }
    
    @end
    
    If any…

    Thanks!
     
  2. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #2
    In the first example objectFromClassOne is an instance variable. Meaning all methods in ClassTwo can access it. This means that it is usually a very bad idea to release and destroy that object in any method other than -dealloc. This could be a fatal flaw, and should be avoided. Often by just moving the [objectFromClassOne release] to the -dealloc method.

    In example 2, objectFromClassOne is just an object in the -doSomething method, and apparently gets destroyed at the end of the -doSomething method.
     
  3. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #3
    To clarify, instance variables are meant to be used as persistent data content of an object instance. Creating and releasing an instance variable within a method makes little sense.

    If you do release an instance variable, the best way to avoid later problems is to then set its pointer value to nil so that other methods do not use a deallocated or incorrect pointer.

    As well it should be in order to avoid a memory leak.
     
  4. CMT thread starter macrumors regular

    CMT

    Joined:
    Aug 24, 2009
    #4
    Thank you jared_kipe and Sydde.

    In my case, ClassTwo would be an Controller class which connects a View to a Model. This model does some math operations and returns an output NSString *.

    So, I'd prefer to do it like the first example, where ClassOne would be the model. But as far as I understand, when I do 'Model *model' (ivar), I'm not creating an object. (tell me if I'm wrong) So in order to use it I have to do [[model alloc] init] somewhere.

    Here's the problem: I include this on the same doSomething method, then each time I call the method I'll be creating an object? And, If I create it but then release, like I wrote in the previous post 1st example, will I be able to create another (with the same pointer I declared)?

    Once again, thanks a lot.
     
  5. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #5
    A declaration like
    Code:
    Model   *model;
    simply reserves space for a pointer. In the case of an instance variable (the first example), you can be fairly certain that its initial value will be nil. In the case of a method variable (the second example), the pointer lives on the stack, so its value is always unknown until you initialize it with something (as in creating an object).

    The second form is generally preferred for temporary objects, as long as you remember to release them. If you do use the first form, you should set the ivar pointer to nil after you release it, just to be safe.
     
  6. CMT thread starter macrumors regular

    CMT

    Joined:
    Aug 24, 2009
  7. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #7
    I'm sort of torn on this myself. Setting it to nil always looks like a good idea at first, but it can make debugging much harder. NSZombie won't work, and what would have been a crash with a useful backtrace will turn into a silent return of nil, which could cause havoc elsewhere in your app.
     
  8. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #8
    Just a tip: You were using names for instance variables that are not recognisable as such. Follow a coding style where instance variables are instantly recognisable in your code. People use different styles, like objectFromClassOne_ or _ objectFromClassOne or m_ objectFromClassOne. If you follow this consequently then you know immediately what an identifier in your code means.
     
  9. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #9
    In almost any case, your model object would be created in -init or through some action from the user. Such as the user types in something and presses a button which fires off a method that takes the typed input and creates a new model object with that input.
     
  10. CMT thread starter macrumors regular

    CMT

    Joined:
    Aug 24, 2009
    #10
    Aha, perfect for what I need. I'll create the the model inside the controller -init overwrite

    Code:
    -(id)init {
    	if (self = [super init]) {
    		myModelObject = [[Model alloc]init];
    	}
    	return self;
    }
    
    and destroy it in -dealloc.

    Code:
    -(void)dealloc {
    	[myModelObject release];
    	[super dealloc];
    }
    
    That way no memory will leak.

    Thanks!

    Best regards
     
  11. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #11
    I believe Apple recommends against using a leading underscore on ivar names because thats what they use for private ivars and it could lead to conflicts (when defining new ivars in your own subclass of a Cocoa class, for example).
     
  12. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #12
    Yep:
     
  13. CMT thread starter macrumors regular

    CMT

    Joined:
    Aug 24, 2009
    #13
    Yes. Well, in other languages and ' _ ' is used for private ivars or functions (like http://codeigniter.com/user_guide/general/controllers.html#private), but as it is @protected by default in Cocoa… not needed
     
  14. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #14
    Only for methods, Apple says its ok for ivars.
     
  15. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #15
    Where do they say that? Use the debugger to spy on virtually any Cocoa object and you will see a ton of private ivars with underscore prefixes (i.e. ones that Apple created that you want to avoid conflict with). Not to mention that an ivar with an underscore prefix would logically lead to an accessor method with an underscore prefix, especially if you are using ObjC 2.0 properties.
     
  16. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #16
    Well they don't say it there specifically but I would assume to not use it for ivars as well. I've personally seen conflicts with this before, so I avoid it entirely now.
     
  17. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #17
    Either they changed their style guidelines fairly recently or I'm going crazy. In the same section where they say not to name private method names with a proceding underscore, they used to say that you were free to do so on private instance variables.

    None the less, they do indicate that if you plan on having private instance variables you should use the @private keyword. The reason for this is that only instances of that class itself can access those ivars. Not even subclasses.

    On the iPhone and 64bit Mac OS you can even have dynamic ivars that have the same name, but are not the same object or value for subclasses.
     

Share This Page