5

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.

StringSection
  • 121
  • 1
  • 5
  • Can you post the given warning ? – Laurent Etiemble Jan 19 '10 at 08:36
  • (Ah I can post comments as I'm still cookied...). Laurent, it is just a yellow Xcode warning: "Warning: assignment from distinct Objective-C type". – StringSection Jan 19 '10 at 09:25
  • The answers from Phillipe and Vladimir have explained the situation. The issue is that the stringValue object is immutable, and so can't be assigned to a mutable string variable. (Vladimir also points out that my NSMutableString *myVar = @"whatever"; code is inherently illegal though not creating the warning in question.) Thanks! – StringSection Jan 19 '10 at 09:32
  • I actually just corrected my original code from NSMutableString *myVar = @"whatever"; to Vladimir's correct syntax of NSMutableString *myVar = [NSMutableString stringWithString:@"whatever"]; to avoid confusion about what is causing the error. – StringSection Jan 19 '10 at 09:48

3 Answers3

7

-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
  • 170,431
  • 36
  • 387
  • 313
  • 2
    Or you can use `[aString mutableCopy]`. – Rob Keniger Jan 19 '10 at 09:13
  • Note that per Vladimir's comment, I've corrected the code in the original post to show a proper NSMutableString being created initially. – StringSection Jan 19 '10 at 09:53
  • 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 Jan 19 '10 at 09:57
  • Thanks Rob, mutableCopy gets the immutable stringValue into the existing mutable variable. – StringSection Jan 19 '10 at 09:58
  • @Vladimir: OK, just wanted to remove any confusion in the original example as to what was causing the warning. – StringSection Jan 19 '10 at 10:02
  • 1
    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 Jan 19 '10 at 17:59
  • 1
    You could also send a message to the literal: NSMutableString *tStr = [@"lala" mutableCopy]; –  Jan 19 '10 at 22:20
4

[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
  • 168,566
  • 31
  • 210
  • 223
0

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
  • 93,976
  • 29
  • 161
  • 209