3
\$\begingroup\$

I read that if an object is made using the init it must be released, but if it's something like this elementFormula = [[NSMutableString stringWithString:@""] it is autoreleased. However, there are some other aspects of memory management that confuse me.

For example, something like [[NSMutableString stringWithString:@""] retain] If I retain an autoreleased object, do I have to release it myself, or is it still autoreleased? Also, if I declare a pointer to an object in the .h and assign it a value in the .m like so completeFormula = [self synthesizeFormula]; without going through the init process, do I have to release completeFormula?

Those are my main concerns, but I have posted the entire code below if needed.

@interface EquationTextField : UIView <KeyInput> {

FormulaKeyboard *keyboard;
int consecutiveElementCount;
int subscriptLength;
int chargeIndex;
NSMutableString *elementFormula;
NSString *lastElementPressed;
NSString *charge;
NSString *state;
NSString *completeFormula;
}

init {

      NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:@"FormulaKeyboard"     owner:self options:nil];

    for (id object in bundle) {
        if ([object isKindOfClass:[FormulaKeyboard class]])
            keyboard = (FormulaKeyboard *)object;
    }   


    self.inputView = keyboard;
    keyboard.delegate = self;


    elementFormula = [[NSMutableString  stringWithString:@""] retain];
    charge = [[NSString alloc] initWithString:@""];
    state = [[NSString alloc] initWithString:@""];



}

 - (void)addElement:(NSString *)currentElement {


if (![currentElement isEqualToString:lastElementPressed])  {

    // when new element is pressed 

    [elementFormula appendString:currentElement];
    lastElementPressed = currentElement;
    consecutiveElementCount = 1;


}


else if ([currentElement isEqualToString:lastElementPressed]) { 

    // when element is pressed consecutively

    if (consecutiveElementCount == 1) {

        // since there is no '1' subscript, nothing needs to be deleted

        [elementFormula appendString:@"₂"]; 
        subscriptLength = 1;


    }


    if (consecutiveElementCount > 1) {

        // deletes last subscript and replaces it with new subscript


        NSArray *subscriptList = [[[NSArray alloc] initWithObjects:@"₂", @"₃", @"₄", @"₅", @"₆", @"₇", @"₈", @"₉", @"₁₀", @"₁₁", @"₁₂", nil] autorelease]; 



        NSRange range = NSMakeRange (([elementFormula length] - subscriptLength), subscriptLength);

        [elementFormula deleteCharactersInRange:range];

        NSString *tempSubscript = [subscriptList objectAtIndex:consecutiveElementCount - 1];
        [elementFormula appendString:tempSubscript];

        subscriptLength = [tempSubscript length];

    }


    if (consecutiveElementCount < 11)
        consecutiveElementCount ++;

}


completeFormula = [self synthesizeFormula];


 }






- (void)changeCharge:(NSString *)chargeIncrease {

NSArray *chargeList = [[[NSArray alloc] initWithObjects:@"⁴⁻", @"³⁻", @"²⁻", @"⁻", @"", @"⁺", @"²⁺", @"³⁺", @"⁴⁺", nil] autorelease];

if ([chargeIncrease isEqualToString:@"+"]) {


    chargeIndex += 1;
    charge = [chargeList objectAtIndex:chargeIndex];


}

else if ([chargeIncrease isEqualToString:@"-"]) {

    chargeIndex -= 1;
    charge = [chargeList objectAtIndex:chargeIndex];


}

completeFormula = [self synthesizeFormula];

}

- (void) changeState:(NSString *)stateName {

state = stateName;

completeFormula = [self synthesizeFormula];


}



- (NSString *)synthesizeFormula {

NSMutableString *synthesizedFormula = [[[NSMutableString alloc] initWithString:elementFormula] autorelease];
[synthesizedFormula appendString:charge];
[synthesizedFormula appendString:state];

return synthesizedFormula;
}



- (void)dealloc
{
[charge release];
[state release];
self.inputView = nil;
keyboard.delegate = nil;
[keyboard release];
[super dealloc];
}
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

It's not init that causes you to have to be responsible for releasing the memory its alloc. If you call alloc, retain or new (this is rarely used these days) then you are responsible for releasing the memory yourself.

So in the case where you had an autoreleased object and you retained it. Then yes you would then be responsible for subsequently releasing it.

The most common side affect where you can be responsible for releasing an object you didn't explicitly call alloc or retain on is with a property that has the retain attribute.

@property (retain) NSString *string;

if you then have the following code somewhere

self.string = [NSString stringWithString:@"This is an autoreleased string typically"];

calling the self.string piece will cause it to retain the value you are setting it with. So you would want to make sure and have the following to clean it up, probably in your dealloc.

self.string = nil;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.