Why does NSString respond to appendString?

前端 未结 3 1958
悲哀的现实
悲哀的现实 2020-12-30 04:11

I was playing with the respondsToSelector method in Objective-C on MacOS-X 10.6.7 and Xcode 4.0.2, to identify if an object would respond to certain messages. According to t

3条回答
  •  滥情空心
    2020-12-30 04:48

    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.

提交回复
热议问题