views:

127

answers:

2

Hey all

Why is substringFromIndex not working for my NSMutableString?

Here code similar to what I have:

NSMutableString *myString = [[NSMutableString alloc] initWithString:@"This is my String"];

[myString substringFromIndex:5

NSLog(@"myString = %@", myString); //will output This is my String

If I use substringFromIndex on NSString it will work, for example like so:

NSString *tempStr = [[NSString alloc] init];
tempStr = [myString substringFromIndex:5]; 
NSLog(@"tempStr = %@", tempStr); //will output is my String 

Why does it not work in the first example, and I have one more question, if I do it using the second method, and then I set:

[myString setString:tempStr];
[tempStr release];

This will result in a crash, I thaught, since I used setString on NSMutableString, that I do not need the NSString and I release it, but apparently that is not the case, however if I use autorelease it will be OK

+1  A: 

That method never alters the string you call it on. It returns a new string in both cases. So assign it to a new string variable and your good.


It's crashing because you over releasing one object and and leaking another. You alloc the first string, then make a new autoreleased string from substringFromIndex:, then release it. You dont need to try this hard.

Simply assign the output of the substring method to a variable, and let it be autoreleased for you. No alloc, no release.


A full proper example might look like this:

NSMutableString *myString = [[NSMutableString alloc] initWithString:@"This is my String"];
NSString *tmpString = [myString substringFromIndex:5];
NSLog(@"tempStr = %@", tempString);
[myString setString:tempStr];

// later do [myString release]

or even simpler:

NSString *myString = @"This is my String";
myString = [myString substringFromIndex:5];
Squeegy
But why doesn't it allow me to do: myString = [myString substringFromIndex:5]; Why is it overreleasing if I release tempStr, since I no longer need tempStr but will need myString for little longer...
Ladislav
`[[NSString alloc] init]` will initialize a new string object. But `substringFromIndex:` returns a completely different string object. So the one you just created is never used. And worse, it's leaking since you never release that object. Objects returned from methods are autoreleased. Meaning they release themselves when its safe. So you are releasing this autoreleased string object and when the autorelease later triggers its already been deallocated and you get a crash.
Squeegy
Is there any difference in using NSMutableString or NSString in case you want to either do substrings or if you want to append strings to it?NSString has stringByAppendingString and NSMutableString has appendString...
Ladislav
Also remember that these are just pointers. `NSString` is immutable, but that doesn't mean you can set `NSString *myString` to a different string. It just means that the string object it currently points to can't change it's internal state. But you are free to point it to a different string all you want. And most of the `NSString` manipulation methods just return a new string that is a transformation of the receiver, but doesn't alter it.
Squeegy
So if I do: NSString *tmpString = [myString substringFromIndex:5]; I do not even have to write [tmpString autorelase]; because it will autorelease by itself by the substringFromIndex method?
Ladislav
Correct. Never `alloc` an object that you get from somewhere else. And never ever `release` object you did not `alloc` or `retain`. So in this case, you dont need to `alloc` or `retain`, and you therefore do not need to `release`.
Squeegy
One more thing, Why can't I do myString = [myString substringFromIndex:5]; XCode will return Incompatible Obj-C types assigning struct NSString expected struct NSMutableString
Ladislav
You don't need NSMutableString here, as the method you are using exists on NSString. It's complaining because myString is a NSSMutableString, but the return value of that method is NSString. If you make your myString simply an NSString, it will work fine.
Squeegy
+1  A: 

[myString substringFromIndex:5] returns a new NSString that starts from the specified index. It does not modify myString.

try this code instead:

NSLog(@"myString = %@", [myString substringFromIndex:5]);
wm_eddie