Short answer: That string is of type NSCFString
, a class that inherits from NSMutableString
, hence it responds to the selectors for the methods declared in NSMutableString
, including superclasses.
Not so short answer: Foundation strings are toll-free bridged with Core Foundation strings. Developers use the opaque types CFStringRef
(bridged with NSString
) and CFMutableStringRef
(bridged with NSMutableString
) to refer to these strings so, at first glance, there are two different types of strings: immutable and mutable.
From a Core Foundation internal implementation perspective, there’s a private type called struct __CFString
. This private type keeps a bit field that stores, amongst other information, whether the string is mutable or immutable. Having a single type simplifies implementation since many functions are shared by both immutable and mutable strings.
Whenever a Core Foundation function that operates on mutable strings is called, it first reads that bit field and checks whether the string is mutable or immutable. If the argument is supposed to be a mutable string but it in fact isn’t, the function returns an error (e.g. _CFStringErrNotMutable
) or fails an assertion (e.g. __CFAssertIsStringAndMutable(cf)
).
At any rate, these are implementation details, and they might change in the future. The fact that NSString
doesn’t declare -appendString:
doesn’t mean that every NSString
instance doesn’t respond to the corresponding selector — think substitutability. The same situation applies to other mutable/immutable classes such as NSArray
and NSMutableArray
. From the developer perspective, the important thing is that the object that’s been returned is of a type that matches the return type — it could be the type itself or any subtype of that type. Class clusters make this a tad more convoluted but the situation is not restricted to class clusters per se.
In summary, you can only expect that a method returns an object whose type belongs to the hierarchy (i.e., either the type itself or a subtype) of the type for the return value. Unfortunately, this means that you cannot check whether a Foundation object is mutable or not. But then again, do you really need this check?
You can use the CFShowStr()
function to get information from a string. In the example in your question, add
CFShowStr((CFStringRef)myString);
You should get an output similar to:
Length 0
IsEightBit 1
HasLengthByte 0
HasNullByte 1
InlineContents 0
Allocator SystemDefault
Mutable 0
Contents 0x0
where
Mutable 0
means that the string is in fact immutable.