Search code examples
iphoneobjective-cxcoderetainalloc

Memory Allocation Question


I have a string which I am updating constantly (~33 times a second). It is used over and over and over again and is omnipresent in a loop I have going. This is the loop:

- (void)add{
    int r = (arc4random() % 30) + 51;
    long long debtInt = [debtString longLongValue];
    long long multiplier = r;
    long long debtAdj = multiplier + debtInt;
    debtString = [NSString stringWithFormat:@"%lli", debtAdj];
    [debtString retain];
    [self formating];
}

- (void)formating{
    NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
    [f setNumberStyle:NSNumberFormatterDecimalStyle];
    NSNumber * myNumber = [f numberFromString:debtString];
    [f release];

    NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
    [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
    [numberFormatter setMaximumFractionDigits:0];
    NSString *formattedNumberString = [numberFormatter stringFromNumber:myNumber];
    [numberFormatter release];

    UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 325, 100)];
    myLabel.font = [UIFont fontWithName:@"Verdana" size: 20.0];
    myLabel.text = formattedNumberString;
    myLabel.textAlignment = UITextAlignmentCenter;

    [self.view addSubview:myLabel];
    [myLabel release];
}

which is fired off by an NSTimer every 0.03 seconds. The one spot where I thought I could logically release the debtString was after it is converted to a long long integer. This, however, crashes the app. If I remove the [debtString retain] line, the app crashes.

The memory build up is quick and fast, it is a 14 byte string. Every second that creates another 462 bytes of mis-allocated memory, that along with all the adjustments, comes out to roughly 3696 byes/sec. This is not a leak I can ignore. I just don't know where to release it in the loop!


Solution

  • If you're committed to doing it this way, you should release your debtString in each iteration of the loop, right before you reassign the value:

    [debtString release];    
    debtString = [NSString stringWithFormat:@"%lli", debtAdj];
    [debtString retain];
    

    However, you're creating a new instance every loop. You'd be better served using a single NSMutableString (like @OscarMk suggested) and updating it each time. And don't create a new UILabel each time. Just create one and update the contents each time through the loop.