topace
topace

Reputation: 1791

Creating a long NSString causing memory issues

My code below is causing my app to quit i.e. get black screen and then see in debugger console: Program received signal: “0”.

Basically it is causing problem when my orderArray has count of 2000 or more. I am using iPhone 3GS with iOS 4.2

Question: Is there a more efficient and less memory consuming way to create my long outStr?

NSString *outStr = @"";

for (int i = 0; i < count; i++) {
    NSDictionary *dict = [[ARAppDelegate sharedAppDelegate].orderArray objectAtIndex:i];
    outStr = [outStr stringByAppendingFormat:@"%@,%@,%@,%@\n", 
              [dict valueForKey:@"CODE"], 
              [dict valueForKey:@"QTY"],
              [[ARAppDelegate sharedAppDelegate].descDict valueForKey:[dict valueForKey:@"CODE"]],
              [[ARAppDelegate sharedAppDelegate].priceDict valueForKey:[dict valueForKey:@"CODE"]]];

}

Update: Thanks to very kind people who helped, below is my modified code:

NSArray *orderA = [ARAppDelegate sharedAppDelegate].orderArray;
NSDictionary *descD = [ARAppDelegate sharedAppDelegate].descDict;
NSDictionary *priceD = [ARAppDelegate sharedAppDelegate].priceDict;
NSMutableString *outStr = [[[NSMutableString alloc] init] autorelease];
for (int i = 0; i < [orderA count]; i++) {
    NSDictionary *dict = [orderA objectAtIndex:i];
            NSString *code = [dict valueForKey:@"CODE"];
    [outStr appendFormat:@"%@,%@,%@,%@\n", 
              code, 
              [dict valueForKey:@"QTY"],
              [descD valueForKey:code],
              [priceD valueForKey:code]];
}


[self emailTxtFile:[NSString stringWithString:outStr]]; 

// This reaches end of method

Upvotes: 3

Views: 183

Answers (1)

mvds
mvds

Reputation: 47114

The problem is that in every iteration a new string object is formed. This consumes a lot of memory. One solution could be to use a local autoreleasepool, but that's rather complicated here.

You should use an NSMutableString, like:

NSMutableString *outStr = [[[NSMutableString alloc] init] autorelease];
for (int i = 0; i < count; i++) {
    NSDictionary *dict = [[ARAppDelegate sharedAppDelegate].orderArray objectAtIndex:i];
    [outStr appendFormat:@"%@,%@,%@,%@\n", 
          [dict valueForKey:@"CODE"], 
          [dict valueForKey:@"QTY"],
          [[ARAppDelegate sharedAppDelegate].descDict valueForKey:[dict valueForKey:@"CODE"]],
          [[ARAppDelegate sharedAppDelegate].priceDict valueForKey:[dict valueForKey:@"CODE"]]];
}

Then you can use outStr, just as if it was an NSString. As Tom points out in the comments, you could turn the NSMutableString into an NSString when you're finished, using:

NSString *result = [NSString stringWithString:outStr];

[outStr release]; // <-- add this line and remove the autorelease
                  //     from the outStr alloc/init line

making your code re-usable and easier to maintain.

Upvotes: 5

Related Questions