Neil
Neil

Reputation: 2058

NSString crashing program, how to fix?

I have the following code:

.h

NSString *mainString;

.m

case 0: 
case 1:
case 2:
if ([typeTo textAlignment] == UITextAlignmentRight) {
     typeTo.text = [NSString stringWithFormat:@""];
     mainString = @"";
     [typeTo setTextAlignment:UITextAlignmentLeft];
     typeTo.text = [NSString stringWithFormat:@"%@%d", typeTo.text, [sender tag]];
     mainString = [NSString stringWithFormat:@"%@%d", mainString, [sender tag]];
} else {
     typeTo.text = [NSString stringWithFormat:@"%@%d", typeTo.text, [sender tag]];
     mainString = [NSString stringWithFormat:@"%@%d", mainString, [sender tag]];
}
NSLog(@"%@",mainString);
break;

Crashes on this line usually.

mainString = [NSString stringWithFormat:@"%@%d", mainString, [sender tag]];

Code works one then crashes. both typeTo.text and mainString start as @"" And text alignment starts left. What am I doing wrong?

Upvotes: 0

Views: 1006

Answers (1)

DarkDust
DarkDust

Reputation: 92336

If you are not using ARC, then you need to either retain the created string or create it with alloc. So either:

mainString = [[NSString stringWithFormat:@"%@%d", mainString, [sender tag]] retain];

or better yet:

mainString = [[NSString alloc] initWithFormat:@"%@%d", mainString, [sender tag]];

This of course means you also need to release it before assigning a new value.

The reason for the crash is likely because you assign the autorelease instance to the pointer, then the object gets autoreleased but the pointer still points to that now-dead object.

Another way would be to use a property with retain or copy keyword. For strings, copy is usually the better solution because you could accidentally pass a NSMutableString and then later modify it.

Edit to answer comments:

In this case, to avoid a memory leak, the following should be done:

[mainString autorelease];
mainString = [[NSString alloc] initWithFormat:@"%@%d", mainString, [sender tag]];

The reason why this is necessary is because the mainString is used as an argument to create a new object, which is then in turn assigned to mainString. So before the initWithFormat: line, mainString pointed to a string object A. After that line, it now points to a new string object B. But you need to make sure to clean up A, which is why the autorelease is necessary. If you don't you'd have a memory leak and eventually your app will run out of memory.

Alternatively, you could also do:

NSString *tmp = mainString;
mainString = [[NSString alloc] initWithFormat:@"%@%d", tmp, [sender tag]];
[tmp release];

The difference is that autorelease says: I need this object for a short while, but some time after I leave this method it must be cleaned up if possible. release says: I don't need the object any more, please clean it up now if possible.

Upvotes: 2

Related Questions