initializing ivars

  • Hi Shawn,

    Actually, sorry, that init was typed into mail. The real init does
    not have the extra semicolon. Here it is (and I still hope it is
    standard).

    - (id) init {
    self = [super init];
    return self;
    }

    However, your messages got me thinking about something I found odd
    running through the debugger.

    If my instance variables consist of something like NSStrings, and I
    use standard accessor methods (return the ivar for getter, release
    ivar, then set ivar to copy of parameter for setter), then everything
    works fine.

    But if the ivar consists of an NSMutableArray (or presumably any
    other collection), then I have to somehow initialize the array or it
    will have 0x0 memory assigned to it and will not respond to attempts
    to add objects. I find that surprising. If I alloc memory for the
    class instance, why wouldn't memory be created for the instance
    variable in one case (arrays) and not the other (non-collection data
    types)?

    I think the answer is that since to set the NSStrings you are
    initially releasing nil (also 0x0 memory status), then it's not a
    problem since it will be copying the address of the variable I send
    as a parameter in the setter. But to add to an array, it must first
    exist.

    Which is why I was asking about a standard way to "reset" or in some
    cases initialize instance variables. Here was my reset method, which
    worked. But I don't see other people doing something similar....

    - (void) reset
    {
    [self setInput: [NSString string]];
    [self setSyllables: [NSMutableArray array]];
    [self setCandidate: [NSString string]];
    [self setRemainder: [NSString string]];
    [self setIsSyllable: NO];
    [self setWasSyllable: NO];
    [self initializeParser];
    // I SHOULDN'T HAVE TO REINITIALILZE THE PARSER,
    // BUT DURING RESET possibilities BECOMES INVALID FOR SOME REASON
    // NEED TO ADDRESS THIS ISSUE LATER
    }

    Curiously, a parser that gets initialized by placing a bunch of
    strings into an NSSet (one of the ivars), disappears unless I
    reinitailize it.  I think it's because I use a convenience
    constructor (    possibilities = [NSSet setWithObjects:), so I guess it
    gets autoreleased after some unspecified amount of time. Probably
    better to go alloc, init, and then set to nil in the dealloc.

    But as for the value initialization I was talking about (input,
    syllables etc.)....does the above approach look strange?

    Daniel

    On Sep 1, 2007, at 12:31 PM, Shawn Erickson wrote:

    > Ah sorry I thought your first sentence "I think the init method is
    > pretty standard." was "I think the _dealloc_ method is pretty
    > standard." when I first read it because I was focusing on the issue
    > you had in dealloc.
    >
    > Anyway your init method is in a way non-standard since it doesn't
    > do anything beyond what you would inherit from your super class, so
    > you don't need to define or declare it.
  • On 9/2/07, Daniel Child <wchild...> wrote:
    > Hi Shawn,
    >
    > Actually, sorry, that init was typed into mail. The real init does not have
    > the extra semicolon. Here it is (and I still hope it is standard).
    >
    > - (id) init {
    > self = [super init];
    > return self;
    > }

    Well it still doesn't do anything useful, so either it isn't needed
    (don't implement) or you need to make it do the work that is needed
    for your class at init time.

    > If my instance variables consist of something like NSStrings, and I use
    > standard accessor methods (return the ivar for getter, release ivar, then
    > set ivar to copy of parameter for setter), then everything works fine.
    >
    > But if the ivar consists of an NSMutableArray (or presumably any other
    > collection), then I have to somehow initialize the array or it will have 0x0
    > memory assigned to it and will not respond to attempts to add objects. I
    > find that surprising. If I alloc memory for the class instance, why wouldn't
    > memory be created for the instance variable in one case (arrays) and not the
    > other (non-collection data types)?
    >
    > I think the answer is that since to set the NSStrings you are initially
    > releasing nil (also 0x0 memory status), then it's not a problem since it
    > will be copying the address of the variable I send as a parameter in the
    > setter. But to add to an array, it must first exist.

    OK I guess you don't understand the difference between an instance
    variable (ivar) and an instance of an object.

    When you state "NSMutableArray* theArray" in a classes @interface
    block the compiler creates an instance variable that can be used to
    _point_ at (aka reference) an instance of NSMutableArray (this is a
    pointer to an object, not an object itself).

    When you allocat an instance of your class the ivar "theArray" will be
    given the value of zero ("nil"). The same things happens for any and
    all ivars regardless of their type.

    Until you change the value of "theArray" it will be nil since you took
    no steps yet to make it reference an instance of NSMutableArray. Also
    given that the value of "theArray" is nil operations like [theArray
    addObject:someObject] will do nothing since attempts to send a message
    to "nil" does nothing.

    To make "theArray" useful (in this context) you would need to allocate
    and initialize a NSMutableArray instance and make "theArray" reference
    that instance.

    In otherwords...
      theArray = [[NSMutableArray alloc] init];

    You would normally do this in your classes designated init method
    ("init" in your example) since after "init" your object should be
    ready to process messages, "do its thing".

    For example...

    - (id) init {
        self = [super init]
        if (self != nil) {
            theArray = [[NSMutableArray alloc] init];
        }
        return self;
    }

    Of course "[[NSMutableArray alloc] init]" allocated an instance of
    NSMutableArray and under the memory contract that means we have a
    retain on that object that we have to release at some point in the
    future when you class is done with that object. This release would
    normally be done in your classes dealloc method.

    For example...

    - dealloc {
      [theArray release];
      [supre dealloc];
    }

    Again the above applies equally to ivars like "NSString* theString",
    "id someObject", etc.

    Now if you want to expose "theArray" to other objects and/or want to
    use an accesor for it you could do something like the following (many
    variations exist, for example to not use the setter in your init or
    dealloc method but instead just use ivar directly as I did above).

    @interface Foo : NSObject {
        NSMutableArray* theArray;
    }
    - (NSMutableArray*) theArray;
    - (void) setTheArray:(NSMutableArray*)newArray;
    @end

    @implementation Foo
    - (id) init {
        self = [super init]
        if (self != nil) {
            [self setTheArray:[NSMutableArray array]];
        }
        return self;
    }

    - dealloc {
        [self setTheArray:nil];

        [supre dealloc];
    }

    - (NSMutableArray*) theArray
    {
        return theArray;
    }

    - (void) setTheArray:(NSMutableArray*)newArray
    {
        if (newArray != theArray) {
            [theArray release];
            theArray = [newArray retain];
        }
    }
    @end

    -Shawn
  • On 9/2/07, Daniel Child <wchild...> wrote:

    > Probably better to go alloc, init, and then set to nil in the dealloc.

    Unless you are using the GCed objective-c runtime you must send it a
    release message. Setting to nil will not cause the instance to
    deallocated.

    Daniel what programming language / development framework are you most
    familiar with? ..knowing that could help us word our answers in way
    that will be more helpful to you.

    -Shawn
previous month september 2007 next month
MTWTFSS
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Go to today