views:

468

answers:

3

This works:

NSString *myVar = @"whatever"; 

NSDecimalNumber *myNum = [NSDecimalNumber decimalNumberWithString:@"10"];

myVar = [myNum stringValue];

This version with mutable string produces warning "assignment from distinct Objective-C type":

NSMutableString *myVar = [NSMutableString stringWithString:@"whatever"];  //UPDATE: CORRECTED CODE

NSDecimalNumber *myNum = [NSDecimalNumber decimalNumberWithString:@"10"];

myVar = [myNum stringValue];

In both cases stringValue is returning an NSCFString. The immutable NSString variable doesn't care, the mutable NSMutableString complains.

P.S. someone please add tags for NSMutableString and stringValue.

+2  A: 

-stringValue returns autoreleased instance of NSString, that is immutable object. Even if you assign it to the mutable string pointer it will not make the string mutable and you will not be able to call mutable string methods on it (btw, the same stays true for your 1st code):

NSMutableString* tStr = @"lala";
[tStr appendString:@"lalala"]; // CRASH! Attempting to mutate immutable object

The correct way to handle it is to create mutable string with convinience method:

NSMutableString* tStr = [NSMutableString stringWithString:@"lala"];
[tStr appendString:@"lalala"]; // OK 
Vladimir
Or you can use `[aString mutableCopy]`.
Rob Keniger
Note that per Vladimir's comment, I've corrected the code in the original post to show a proper NSMutableString being created initially.
StringSection
when you assign a string like: myVar = [myNum stringValue]; you discards all previous assignments - it does not matter how you previously created your string, now myVar contains the result of -stringValue and previous value is lost.
Vladimir
Thanks Rob, mutableCopy gets the immutable stringValue into the existing mutable variable.
StringSection
@Vladimir: OK, just wanted to remove any confusion in the original example as to what was causing the warning.
StringSection
Remember that `-mutableCopy` will return an object with a +1 retain count, not autoreleased. If you happen to already have a mutable string, using `-[NSMutableString setString:]` is cleaner and possibly faster.
Quinn Taylor
You could also send a message to the literal: NSMutableString *tStr = [@"lala" mutableCopy];
Preston
+4  A: 

[myNum stringValue] returns a NSString, not NSMutableString, so this will generate the warning.

If you would try to manipulate the instance of myVar later on (assuming it's a mutable string), you would get an exception, because the object is not a mutable string at all.

Philippe Leybaert
A: 

You cannot make an immutable string into a mutable one simply by assigning it to a variable of type NSMutableString *. What you're doing is essentially:

NSString *immutableStr = @"Mayonnaise";
NSMutableString *mutableStr = immutableStr;

Both variables in this case point to exactly the same constant string object (the pointers will compare equal). You will also get a warning because you are attempting to set a variable of type NSMutableString * with an incompatible value of type NSString *. It is incompatible because NSMutableString * provides methods and behaviour that NSString * doesn't, so when you try to use NSMutableString's behaviour, you will get runtime errors because the actual object being pointed to by the variable is not an NSMutableString.

dreamlax