Why stringByAppendingFormat isn't changing your NSString


A few months ago, Kinglee posted a few questions, including one about stringByAppendingFormat.It’s been several months so I didn’t want to resurrect that thread, but I had the same problem with stringByAppendingFormat as Kinglee, so thought I’d post the answer for the next person who bumps into this.

The stringByAppendingFormat message doesn’t change the NSString you send it to because it isn’t allowed. NSString objects are immutable objects, so they can’t be modified after they are created. Instead, stringByAppendingFormat creates a new NSString object that contains the contents of the original NSString object plus the appended text, and returns a pointer to that new object. If you don’t save that returned pointer somewhere, the new object is lost. So in this code:

// This code doesn't work right NSString *descriptionString = [[NSString alloc] init]; [descriptionString stringByAppendingFormat:@"\nName of container : %@", [self containerName]]; [descriptionString stringByAppendingFormat:@"\nTotal value : $%d", [self totalValueInDollars]]; [descriptionString stringByAppendingFormat:@"\nItems in container :\n%@", [self container]];the new objects created by stringByAppendingFormat are thrown away and descriptionString continues to point to the empty string returned by init.

If you want to use stringByAppendingFormat to update a string, you need to explicitly save the returned NSString pointer each time:

// This code does work correctly NSString *descriptionString = [[NSString alloc] init]; descriptionString = [descriptionString stringByAppendingFormat:@"\nName of container : %@", [self containerName]]; descriptionString = [descriptionString stringByAppendingFormat:@"\nTotal value : $%d", [self totalValueInDollars]]; descriptionString = [descriptionString stringByAppendingFormat:@"\nItems in container :\n%@", [self container]];
Since NSString objects aren’t mutable objects, you can’t send a message that would directly modify descriptionString. However, if you change descriptionString to a NSMutableString, then you can modify it directly by using appendFormat. This message creates the same appended text as stringByAppendingFormat, but saves the result back into the NSMutableString it was sent to. Explicitly saving the results is no longer necessary (or even possible - appendFormat has no return value):

//This code generates the same results as the preceding code block NSMutableString *descriptionString = [[NSMutableString alloc] init]; [descriptionString appendFormat:@"\nName of container : %@", [self containerName]]; [descriptionString appendFormat:@"\nTotal value : $%d", [self totalValueInDollars]]; [descriptionString appendFormat:@"\nItems in container :\n%@", [self container]];