No alloc/init needed for @property instance vars?

Discussion in 'Mac Programming' started by zippyfly, Jul 7, 2010.

  1. zippyfly macrumors regular

    Joined:
    Mar 22, 2008
    #1
    Hi,

    When declaring @property(ies), are the objects automatically allocated? Because I don't see any alloc/init being applied, and the method implementations that use the instance variables don't seem to do it either?

    Code:
    #import <Foundation/Foundation.h>
    
    @interface NewObjEntity : NSObject {
    
    	NSString *varOne;
    	int varTwo;
    	NSDate *dateVar;
    	
    }
    
    @property (nonatomic, copy) NSString *varOne;
    @property (nonatomic) int varTwo;
    @property (nonatomic, readonly) NSDate *dateVar;
    and in .m

    Code:
    @synthesize varOne, varTwo, dateVar;
    
     
  2. seepel macrumors 6502

    seepel

    Joined:
    Dec 22, 2009
    #2
    With synthesize it will automatically create setters and getters, but the objects won't be instantiated until you set them. So I guess the short answer is no, they are not automatically allocated.
     
  3. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #3
    If you had to write the accessor methods by hand, where would you use alloc/init in those methods and why?

    For example, if I call [someNewObj setVarOne: @"somestring"]; where would you need alloc/init in the setVarOne: method? If the accessor needs to copy an object, it will do that by using the copy method.
     
  4. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #4
    First of all, the int property is a primitive type, so there's never an alloc/init involved there. The NewObjEntity objects automatically have some space to store a full integer value.

    With the two other properties, they are pointers to NSString and NSDate. Like with the integer, space for the pointers is automatically contained in objects of this class. The actual objects that these pointers refer to and the space to store them isn't created until you (or another method) alloc/init's it. Objects of type NewObjEntity do not store entire NSDate and NSString objects within the object's memory; they just store pointers to memory that is elsewhere on the heap.
     
  5. zippyfly thread starter macrumors regular

    Joined:
    Mar 22, 2008
    #5
    Hi - yup, I understand the instance variables are pointers. And I get that alloc/init should not be happening at the accessor implementation.

    I am thinking the alloc/init should happen at the (designated) initializer for NewObjEntity, when it calls [super init] and then alloc/init the two pointers and maybe sets the int to zero or something.

    Would that be correct?
     
  6. misee macrumors member

    Joined:
    Jul 4, 2010
    #6
    Yes, the instantiation of default values for your instance variables should happen in your initializer method.
    Here's what I would do for your NewObjEntity class:
    Code:
    - (id)init {
        if ((self = [super init]) == nil)
            return nil;
        
        [self setVarOne:@"default value"];
        [self setVarTwo:33];
        [self _setDateVar:[NSDate date]]; // Let's say _setDateVar: is a private setter you and implemented
        
        return self;
    }
    
    Note that I'm using the accessors. That way, I don't have any redundant code and if one setter method could affect a different value or require certain checks (a string might need a specific format), this is automatically taken care of. Even if you don't need it at first, you might later. Plus, I think it's nicer :p.
    Also, if you create an instance of an object and have ownership, don't forget to autorelease it. For example, you could change @"default value" to [[[NSString alloc] initWithFormat:"default %@", @"value"] autorelease] (a somewhat useless example, but you get the idea).
     
  7. zippyfly thread starter macrumors regular

    Joined:
    Mar 22, 2008
    #7
    Hi sorry, can you help clarify this part please:

    Code:
        if ((self = [super init]) == nil)
            return nil;
    
    The nested argument and comparison to nil is a bit confusing to me.

    The other parts I understand.

    Thanks!
     
  8. misee macrumors member

    Joined:
    Jul 4, 2010
    #8
    Code:
    if ((self = [super init]) == nil)
        return nil;
    
    is equivalent to writing
    Code:
    self = [super init];
    if (self == nil)
        return nil;
    I just prefer to have all in one statement, so i put the the assignment to self in the brackets to make it clear that I want to assign the value, and THEN compare to nil.
    the if ((self = [super init]) == nil) first assigns the value returned by [super init]. Then, this assigned value is compared to nil. If it is nil, I simply return nil and the rest of the init method is never executed.
    You could also write if (!(self = [super init])), but the comparison to nil seems more natural to me when I read the code. You'll have to figure out which way you want to do things yourself, this is just my way (and by no means the only valid one).
     
  9. GeeYouEye macrumors 68000

    GeeYouEye

    Joined:
    Dec 9, 2001
    Location:
    State of Denial
    #9
    While we're on the topic, if you're not running garbage collected, don't forget to release your object ivars in -dealloc.
     
  10. zippyfly thread starter macrumors regular

    Joined:
    Mar 22, 2008

Share This Page