views:

162

answers:

3

The code below compiles and runs, BUT according to all iPhone development books and Apple documentation it shouldnt! Can someone please explain to me how come immutable NSString allows to change its values after it has been set? I thought I had to use NSMuttableString to change context of the same string variable? I am using SDK 3.1.

NSString *test =[[NSString alloc] initWithString:@"TEST"];
[test release];
test = @"TEST2";
+5  A: 

You aren't mutating the string, you are just reassigning the variable test to point to a different string. The original string hasn't been modified.

Mark Byers
Ok, makes sense. Then what do THEY mean by mutating strings in obj C? And why in every book they say to create new string when assigning new values to NSString? Thank you!
Igor Kilimnik
They mean changing individual characters of a string, for example changing 'Hello, world!" to "Yello, world!" by changing the first character to a "Y" and leaving the rest unchanged. This sort of operation is only possible if strings are mutable, as they are in C, for example.
Mark Byers
+5  A: 

TEST and TEST2 are two different strings pointed to by the *test pointer.

You are not changing the contents of the explicitly allocated NSString object from the first line of code but pointing *test to another object.

Niels Castle
+2  A: 

Perhaps the following example will add upon the replies from Mark and Niels and help clarify things.

Immutable strings

// Setup two variables to point to the same string
NSString * str1 = @"Hello World";
NSString * str2 = str1;

// "Replace" the second string
str2 = @"Hello ikilimnik";

// And list their current values
NSLog(@"str1 = %@, str2 = %@", str1, str2);

Mutable strings

// Setup two variables to point to the same string
NSMutableString * str1 = [NSMutableString stringWithString:@"Hello World"];
NSMutableString * str2 = str1;

// "Replace" the second string
[str2 setString:@"Hello ikilimnik"];

// And list their current values
NSLog(@"str1 = %@, str2 = %@", str1, str2);

Notice when you use the immutable NSString class that the only way to "replace" a string is to create a new string and update your variable "str2" to point to it. This however doesn't affect what "str1" is pointing to, so it will still reference the original string.

In the NSMutableString example, we don't create a second string, but instead alter (mutate) the contents of the existing "Hello World" string. Since both variables continue to point to the same string object, they will both report the new value in the call to NSLog.

It's important to differentiate between a pointer variable and the actual object it points to. A NSString object is immutable, but that doesn't stop you from changing the value of a variable which points to a string.

The data type "NSString *" is a pointer to a NSString object, not the object itself. If you set a break point at either of the NSLog statements within the XCode debugger, you may like to check the raw value of each variable to clarify this.

Christopher Fairbairn
+1 for actually explaining and not just answering...
Niels Castle
Thank you Christopher, but what about example like this:NSString *str = @"one";str = [str stringByAppendingString:@"two"];Are you saying that even though I using same variable, I am creating two different objects? Also what happens to these NSString objects we create explicitly, do they get cleaned up by autorelease?
Igor Kilimnik
Yes that will create two immutable string objects. "one" and "onetwo". One of the benifits of mutable strings is they can help avoid additional temporary string objects if you perform a lot string appending style operations like the example you provided. This can provide speed and memory usage efficiency gains.
Christopher Fairbairn
With respect to what happens to those previous string objects (such as "one") they follow standard Objective-C memory management rules, so it depends upon how they were created. In your example, they are treated slightly special due to being string constants within the source code of your application, if they were created programatically they may be dealt with via the autorelease pool, or you may need to explictly send them a release message. Search for the "Memory Management Programming Guide for Cocoa" document if you're interested in more detail.
Christopher Fairbairn
Got it, what happens to the NSString object when I say NSString *str = nil;Will it be automatically released?
Igor Kilimnik
Or lets say I used it in my code and then say str=nil;
Igor Kilimnik