John
John

Reputation: 613

Strange NSString stringByAppendingString behavior

I have an object that is appending a local string to another, and then handing that to an instance variable. This StringObj is being held by the calling UITableViewController. On the first call, fullCmdString has the string correctly. However, on 2nd call, the fullCmdString is null, or full of weird data (looks like data in odd mem location). My best guess is that stringByAppendingString is returning a reference to inStr, and not a new NSString object, so the data is going out of scope. Can anyone shed some light on this?

#import "StringObj.h"

@synthesize fullCmdString;

- (void)assemble:(NSString *)inStr {
    NSString *add = @"text added";

    //doesn't hold onto string
    fullCmdString = [NSString stringWithString:[inStr stringByAppendingString:add]];  

    //doesn't hold onto string either
    fullCmdString = [inStr stringByAppendingString:add];

    //works great
    fullCmdString = @"basic text text added";

}

Upvotes: 1

Views: 2551

Answers (3)

dreamlax
dreamlax

Reputation: 95405

// creates an autoreleased string
fullCmdString = [NSString stringWithString:[inStr stringByAppendingString:add]];  

// also creates an autoreleased string
fullCmdString = [inStr stringByAppendingString:add];

// works great, not an autoreleased string
fullCmdString = @"basic text text added";

An autoreleased string gets sent a release message at the end of the run loop iteration (along with everything else in the autorelease pool). If you want it to survive the run loop iteration, avoid putting it in the autorelease pool, or explicitly retain it:

// OK! Avoid the autorelease pool (at least, for fullCmdString)
fullCmdString = [[NSString alloc] initWithString:[inStr stringByAppendingString:add]]; 

// also OK! It's in the pool, but it's also been retained.
fullCmdString = [[inStr stringByAppendingString:add] retain];

// also OK
fullCmdString = @"basic text text added";

See the Cocoa memory management rules for more information. This guide will tell you that anything that you've explicitly allocated or retained—like the above—you will also have to explicitly release when you are done with it.

Upvotes: 1

Chuck
Chuck

Reputation: 237110

Cocoa memory management doesn't involve scope. Whether an object lives or dies is determined by ownership — if another object owns it (by having created it with alloc, new or copy, or claiming ownership with retain), it will stay around. When an object doesn't have any more owners, it can go away. In your case, you want to keep that NSString object around in fullCmdString, but you don't do anything to claim ownership of it, so it just silently goes away and becomes a garbage pointer.

I'd strongly suggest reading Apple's memory management rules. It's a very simple set of guidelines, but it makes all the difference between a working program and one with weird bugs like this.

Upvotes: 2

Grant Paul
Grant Paul

Reputation: 5902

You need to retain it: otherwise it will be released at the end of the current scope, as stringByAppendingString returns an autoreleased object.

Please read the cocoa memory management guide.

Upvotes: 1

Related Questions