mutability?

  • hello,

    we actually need to be able to distinguish
    mutable versus immutable instances of class clusters
    such as NSString, NSArray, NSDictionary etc.

    it does however turn out that all NSStrings
    are CFStrings and that they say yes if
    asked [isKindOfClass:[NSMutableString class]].

    on the other hand if you create an immutable
    NSString and send a mutating message
    you get an exception that shows that this
    string knows about its immutability.

    but I was unable to find any API that
    would retreive this mutability information...

    any help?

    guenther
    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On 07.07.2004, at 16:13, Guenther Fuerthaller wrote:
    > it does however turn out that all NSStrings
    > are CFStrings and that they say yes if
    > asked [isKindOfClass:[NSMutableString class]].

    Well, I had the same problem with dictionaries, I assume a similiar
    "solution" exists for strings.

    Apparently there is _no_ public API for finding that out, which I
    personally consider a major bug. My current workaround for dictionaries
    looks like:

        bool _CFDictionaryIsMutable(CFDictionaryRef dict);

        if ([object isKindOfClass:NSCFDictionaryClass] &&
            !_CFDictionaryIsMutable((CFDictionaryRef)object))

    But someone said that _CFDictionaryIsMutable is deprecated and not
    unlikely to be removed in upcoming OSX versions :-|

    So apparently the only portable "solution" is to wrap all mutations in
    exception handlers ...

    regards,
      Helge
    --
    http://docs.opengroupware.org/Members/helge
    OpenGroupware.org

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • The question in these cases is why you need to know that an object you
    didn't create is mutable or not... (If you created it, presumably you
    know, and you can remember the state.)

    I'm asking this because some decisions that are made based on the
    mutability of an object you don't own can be dangerous, as you don't
    know whether the object is actually part of some other graph of
    objects.

    Ali

    Begin forwarded message:

    > From: Helge Hess <helge.hess...>
    > Date: July 7, 2004 11:02:41 PDT
    > To: Guenther Fuerthaller <Guenther.Fuerthaller...>
    > Cc: <macosx-dev...>
    > Subject: Re: mutability?
    >
    > On 07.07.2004, at 16:13, Guenther Fuerthaller wrote:
    >> it does however turn out that all NSStrings
    >> are CFStrings and that they say yes if
    >> asked [isKindOfClass:[NSMutableString class]].
    >
    > Well, I had the same problem with dictionaries, I assume a similiar
    > "solution" exists for strings.
    >
    > Apparently there is _no_ public API for finding that out, which I
    > personally consider a major bug. My current workaround for
    > dictionaries looks like:
    >
    > bool _CFDictionaryIsMutable(CFDictionaryRef dict);
    >
    > if ([object isKindOfClass:NSCFDictionaryClass] &&
    > !_CFDictionaryIsMutable((CFDictionaryRef)object))
    >
    > But someone said that _CFDictionaryIsMutable is deprecated and not
    > unlikely to be removed in upcoming OSX versions :-|
    >
    > So apparently the only portable "solution" is to wrap all mutations in
    > exception handlers ...
    >
    > regards,
    > Helge
    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On 7 Jul 2004, at 19:02, Helge Hess wrote:

    > Apparently there is _no_ public API for finding that out, which I
    > personally consider a major bug. My current workaround for
    > dictionaries looks like:
    >
    > bool _CFDictionaryIsMutable(CFDictionaryRef dict);
    >
    > if ([object isKindOfClass:NSCFDictionaryClass] &&
    > !_CFDictionaryIsMutable((CFDictionaryRef)object))
    >
    > But someone said that _CFDictionaryIsMutable is deprecated and not
    > unlikely to be removed in upcoming OSX versions :-|

    bool _CFArrayIsMutable(CFArrayRef array);
    bool _CFDictionaryIsMutable(CFDictionaryRef dict);
    bool _CFSetIsMutable(CFSetRef set);
    bool _CFCharacterSetIsMutable(CFCharacterSetRef cset);
    Boolean __CFStringIsMutable(CFStringRef str);

    I don't see any reason why they would be deprecated, although they only
    seem to be used internally within Foundation. But yes, of course it is
    entirely possible that they won't exist in future releases.

    It's generally considered bad practice to actually test for mutability
    - you should know whether or not it's mutable from the selector that
    you obtained it from (if you did a mutableCopy, or you did an
    NSMutable* init..., or whatever). If you mutate something that, while
    mutable, isn't expected to be mutated, you could have problems.

      -- Finlay

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • appreciate your participation, hello!

    > I'm asking this because some decisions that are made based on the
    > mutability of an object you don't own can be dangerous...

    nobody here intends to use such a mutability check
    to mutate a foreign object, not with me!

    to give a short illustration of the background,
    consider a convenient type mapping:
    name <--> NS(Immutable)String
    string <--> NSMutableString
    where the types name/string originate
    from a ps/pdf world.

    another operation that uses mutability
    is what I called -(id)deepMutabilityPreservingCopy.

    another operation that uses mutability
    is an object archiver that may use immutability
    as sufficient to unify instances via isEqual.

    > (If you created it, presumably you know, and you can remember the state.)
    sometimes, but in general this would require
    a wrapping object/struct to store that state.

    I hope you can aggree on my scenarios that
    there might be some reasonable use cases
    for the mutability status of an object.

    regards
    guenther

    Ali Ozer <aozer...>
    07.07.2004 20:19

    To
    Guenther Fuerthaller <Guenther.Fuerthaller...>
    cc
    Ali Ozer <aozer...>, <macosx-dev...>
    Subject
    Re: mutability?

    The question in these cases is why you need to know that an object you
    didn't create is mutable or not... (If you created it, presumably you
    know, and you can remember the state.)

    I'm asking this because some decisions that are made based on the
    mutability of an object you don't own can be dangerous, as you don't
    know whether the object is actually part of some other graph of
    objects.

    Ali

    Begin forwarded message:

    > From: Helge Hess <helge.hess...>
    > Date: July 7, 2004 11:02:41 PDT
    > To: Guenther Fuerthaller <Guenther.Fuerthaller...>
    > Cc: <macosx-dev...>
    > Subject: Re: mutability?
    >
    > On 07.07.2004, at 16:13, Guenther Fuerthaller wrote:
    >> it does however turn out that all NSStrings
    >> are CFStrings and that they say yes if
    >> asked [isKindOfClass:[NSMutableString class]].
    >
    > Well, I had the same problem with dictionaries, I assume a similiar
    > "solution" exists for strings.
    >
    > Apparently there is _no_ public API for finding that out, which I
    > personally consider a major bug. My current workaround for
    > dictionaries looks like:
    >
    > bool _CFDictionaryIsMutable(CFDictionaryRef dict);
    >
    > if ([object isKindOfClass:NSCFDictionaryClass] &&
    > !_CFDictionaryIsMutable((CFDictionaryRef)object))
    >
    > But someone said that _CFDictionaryIsMutable is deprecated and not
    > unlikely to be removed in upcoming OSX versions :-|
    >
    > So apparently the only portable "solution" is to wrap all mutations in
    > exception handlers ...
    >
    > regards,
    > Helge

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • Hello,

    Actually the problem is not you the case, but that isKindOfClass and
    isMemberOfClass don't do the right thing for the string classes (and
    probably other toll-free bridged classes). From the user's perspective,
    you would expect these methods (a contract) to work regardless of
    whether they are toll-bridged or not. This is something that should be
    fixed.

    /a

    On Jul 8, 2004, at 4:38 AM, Guenther Fuerthaller wrote:

    > I hope you can aggree on my scenarios that
    > there might be some reasonable use cases
    > for the mutability status of an object.

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On 07.07.2004, at 20:19, Ali Ozer wrote:
    > The question in these cases is why you need to know that an object you
    > didn't create is mutable or not... (If you created it, presumably you
    > know, and you can remember the state.)

    A somewhat weird question as this can be generalized as why reflection
    and runtime instrospection is useful and necessary. Hopefully we don't
    need to discuss this ;-)
    All code which does Objective-C reflection to discover what messages
    can be send fail on the mentioned Foundation classes (eg immutable
    objects respond to setObject:forKey: which is IMHO clearly a design
    mistake in the ObjC context).

    I consider it somewhat obvious that you have reusable code that deals
    with generic objects. And in a non-trivial application/framework you
    almost never know how an object was constructed even if you have it
    under control (IMHO construction should never be relevant for object
    behaviour?!). After all thats one reason why reference counting / GC is
    useful (passing an objects around).

    > I'm asking this because some decisions that are made based on the
    > mutability of an object you don't own can be dangerous

    You don't need to "own" it, a client object which owns the object can
    give the object to some other utility class which does some processing
    on it. So its an intended and documented mutation on the object
    triggered by the client.
    I'm not talking about some accessor method which checks for mutability
    to avoid creating a mutable copy (which clearly is a bug).

    The point where we stumbled across this is actually
    WOKeyPathAssociation which needs to know whether the bound object is
    mutable or not (so whether it should try to push values into it or just
    retrieve them). Actually WOAssociation even has a reflection methods
    for that (-isValueConstant, -isValueSettable).

    All sorts of bridges are in this category as well.

    BTW: if Foundation is going to keep the mutable/immutable distinction,
    I would actually prefer a general method -(BOOL)isImmutable in NSObject
    (or some protocol implemented by the collections) -isKindOfClass: is
    kind of a Javaish hack too.

    Further, -respondsToSelector:@(setObject:forKey:) could return NO for
    the NSCFDictionary (and maybe nil for -methodForSelector:) if the
    object is created immutable to properly support Foundation reflection.

    Greets,
      Helge
    --
    http://docs.opengroupware.org/Members/helge
    OpenGroupware.org

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • >
    > BTW: if Foundation is going to keep the mutable/immutable distinction,
    > I would actually prefer a general method -(BOOL)isImmutable in
    > NSObject (or some protocol implemented by the collections)
    > -isKindOfClass: is kind of a Javaish hack too.

    Actually these methods predate Java by 10+ years (1988)

    ObjC had:

    -isKindOf:
    -isKindOfClassNamed:
    -isMemberOf:
    -isMemberOfClassNamed:
    -conformsTo:
    +conformsTo:
    +instancesRespondTo:

    -methodFor:
    +instanceMethodFor:
    -descriptionForMethod:
    +descriptionForInstanceMethod:

    +class
    -class
    +superclass
    -superclass
    +name

    The current methods were tweaked with <objc/Object.h> ceased to be the
    root class and NSObject showed up in 1993 or there about.

    [if you ask me, the introspection mechanism was pretty rich considering
    that it was still the dark ages, (Pascal was still very prevalent and C
    was only popular in UNIX) - I am not a SmallTalk developer, it is
    possible that these things came from there.]

    >
    > Further, -respondsToSelector:@(setObject:forKey:) could return NO for
    > the NSCFDictionary (and maybe nil for -methodForSelector:) if the
    > object is created immutable to properly support Foundation reflection.

    + 100. The contract of NSObject needs to be supported regardless of the
    implementation.

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • Fuerthaller wrote:

    [...]
    > I hope you can aggree on my scenarios that
    > there might be some reasonable use cases
    > for the mutability status of an object.

    Like you I think there are perfectly legitimate use cases where it
    makes sense to determine at run-time whether a string is mutable,
    especially in a dynamic language like Objective-C. Yes, this can be
    misused and dangerous, but no more than the possibility of asking an
    object about its class. And I hope no one is thinking about removing
    this feature from Objective-C ;-)

    I don't think that the right way to offer information about mutability
    would be to add a public API. As you noted, the problem at hand comes
    from the fact that, in the current implementation, non-mutable strings
    are instances of a subclass of NSMutableString (how something like that
    can pass design reviews and finds its way into the, otherwise
    excellent, major framework of a major operating system will be a
    subject of amazement for generations of developers). Just fix this
    nonsense and the problem will disappear.

    Best,

    Philippe Mougin
    F-Script: Interactive and scripting environment for Cocoa.
    http://www.fscript.org

    PS: I originally sent this e-mail to the wrong mailing list. Sorry,
    unintended cross-posting.

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Jul 8, 2004, at 11:40 AM, Philippe Mougin wrote:

    > Fuerthaller wrote:
    >
    > [...]
    >> I hope you can aggree on my scenarios that
    >> there might be some reasonable use cases
    >> for the mutability status of an object.
    >
    > Like you I think there are perfectly legitimate use cases where it
    > makes sense to determine at run-time whether a string is mutable,
    > especially in a dynamic language like Objective-C. Yes, this can be
    > misused and dangerous, but no more than the possibility of asking an
    > object about its class. And I hope no one is thinking about removing
    > this feature from Objective-C ;-)
    >
    > I don't think that the right way to offer information about mutability
    > would be to add a public API. As you noted, the problem at hand comes
    > from the fact that, in the current implementation, non-mutable strings
    > are instances of a subclass of NSMutableString (how something like
    > that can pass design reviews and finds its way into the, otherwise
    > excellent, major framework of a major operating system will be a
    > subject of amazement for generations of developers).

    > Just fix this nonsense and the problem will disappear.

    Well not fully. APIs can say they return an immutable objects yet they
    are free to return a mutable one since mutable objects are a refinement
    of immutable versions in Cocoa. So looking at the object to see if it
    is mutable or not can mislead you on what the intent was of the code
    that generated the instance for you.

    Of course ideally those APIs should return a copy (immutable copy) of
    any mutable version used internally if the API implies that what you
    get back is unchanging, etc. In theory NSProxy object can be used as
    well to prevent unwanted modification (say the returned object should
    track changes but not allow changes by others).

    -Shawn

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Jul 7, 2004, at 1:19 PM, Ali Ozer wrote:

    > The question in these cases is why you need to know that an object you
    > didn't create is mutable or not... (If you created it, presumably you
    > know, and you can remember the state.)
    >
    > I'm asking this because some decisions that are made based on the
    > mutability of an object you don't own can be dangerous, as you don't
    > know whether the object is actually part of some other graph of
    > objects.
    >
    I am sorry Ali, but the following is just plain wrong, no matter what
    the intentions were:

    id obj=[[NSString alloc]init];

    //... somewhere else later
    if([obj isKindOfClass:[NSMutableString class]])
    {
      [obj appendString:@"Test"];
    }

    -> An uncaught exception was raised
    -> Attempt to mutate immutable NSString with appendString:

    As I have said many times since their inception for Openstep: The Class
    Clusters are a poor design, and their implementation is even worse.

    Gerd

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Jul 8, 2004, at 12:26 PM, Gerd Knops wrote:

    > I am sorry Ali, but the following is just plain wrong, no matter what
    > the intentions were:
    >
    > id obj=[[NSString alloc]init];
    >
    > //... somewhere else later
    > if([obj isKindOfClass:[NSMutableString class]])
    > {
    > [obj appendString:@"Test"];
    > }
    >
    > -> An uncaught exception was raised
    > -> Attempt to mutate immutable NSString with appendString:
    >
    > As I have said many times since their inception for Openstep: The
    > Class Clusters are a poor design, and their implementation is even
    > worse.

    Have you tried this?

    if ([obj respondsToSelector: @selector(appendString:)] {
      ....
    }

      - Scott

    --
    Tree House Ideas
    http://treehouseideas.com/

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • Yes and it returns true on NSString

    /a

    On Jul 8, 2004, at 2:39 PM, Scott Stevenson wrote:

    >
    > On Jul 8, 2004, at 12:26 PM, Gerd Knops wrote:
    >
    >> I am sorry Ali, but the following is just plain wrong, no matter what
    >> the intentions were:
    >>
    >> id obj=[[NSString alloc]init];
    >>
    >> //... somewhere else later
    >> if([obj isKindOfClass:[NSMutableString class]])
    >> {
    >> [obj appendString:@"Test"];
    >> }
    >>
    >> -> An uncaught exception was raised
    >> -> Attempt to mutate immutable NSString with appendString:
    >>
    >> As I have said many times since their inception for Openstep: The
    >> Class Clusters are a poor design, and their implementation is even
    >> worse.
    >
    > Have you tried this?
    >
    > if ([obj respondsToSelector: @selector(appendString:)] {
    > ....
    > }
    >
    >
    > - Scott
    >
    > --
    > Tree House Ideas
    > http://treehouseideas.com/
    >
    > _______________________________________________
    > MacOSX-dev mailing list
    > <MacOSX-dev...>
    > http://www.omnigroup.com/mailman/listinfo/macosx-dev
    >
    >

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Jul 8, 2004, at 2:39 PM, Scott Stevenson wrote:

    >
    > On Jul 8, 2004, at 12:26 PM, Gerd Knops wrote:
    >
    >> I am sorry Ali, but the following is just plain wrong, no matter what
    >> the intentions were:
    >>
    >> id obj=[[NSString alloc]init];
    >>
    >> //... somewhere else later
    >> if([obj isKindOfClass:[NSMutableString class]])
    >> {
    >> [obj appendString:@"Test"];
    >> }
    >>
    >> -> An uncaught exception was raised
    >> -> Attempt to mutate immutable NSString with appendString:
    >>
    >> As I have said many times since their inception for Openstep: The
    >> Class Clusters are a poor design, and their implementation is even
    >> worse.
    >
    > Have you tried this?
    >
    > if ([obj respondsToSelector: @selector(appendString:)] {
    > ....
    > }
    >
    That's beside the point. And the fact that it returns true goes to show
    how perverted this situation really is... Basically there is an object
    that claims to be an NSMutableString, and then complains bitterly if
    you treat it as such. OOP at it's worst!

    Gerd

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Jul 8, 2004, at 1:21 PM, Gerd Knops wrote:

    > That's beside the point. And the fact that it returns true goes to
    > show how perverted this situation really is... Basically there is an
    > object that claims to be an NSMutableString, and then complains
    > bitterly if you treat it as such. OOP at it's worst!

    Eh, not sure I agree with that. I haven't followed this thread closely,
    but every language/framework has its own idea of how to implement the
    ideals of OO ideals.

    One of the themes in Cocoa is "loosely coupled". Personally, I don't
    think you should worry about the implementation details of the object
    you acquire from another source. That's somewhat heavy handed. If you
    need a mutable string, take the string object and do a -mutableCopy. If
    you need to apply changes back to the source, send the new object to
    the appropriate setter.

    I think you could argue that this is a better approach because it gives
    the source of the original string the opportunity to do additional work
    when changes are made to the string. Changing the contents out from
    under the source means it may not be able to keep something else in
    sync easily.

    I do, however, agree that if something says it can respond to a
    selector, it should.

        - Scott

    --
    Tree House Ideas
    http://treehouseideas.com/

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • Time to file a bug I guess.
    It seems that most of the CF based classes are implemented as one class
    for their mutable and non-mutable parts.
    NSAttributedString and NSMutableAttributedString which are non CF based
    do not show that stupid behavior. Hope that Tiger will fix this! And
    because of the NDA I will have no way to tell :-(

    Here a sample code:

    > #import <Foundation/Foundation.h>
    >
    > int main (int argc, const char * argv[]) {
    > NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    >
    > // insert code here...
    > NSString *str = [NSString stringWithFormat:@"Hello %d times",3];
    > NSMutableString *mstr = [[[NSMutableString alloc] init] autorelease];
    > NSArray *array = [NSArray
    > arrayWithObjects:@"one",@"two",@"three",nil];
    > NSMutableArray *marray = [[[NSMutableArray alloc] init] autorelease];
    > NSSet *set = [NSSet setWithObjects:@"one",@"two",@"three",nil];
    > NSMutableSet *mset = [[[NSMutableSet alloc] init] autorelease];
    > NSAttributedString *ats = [[NSAttributedString alloc]
    > initWithString:@"I am an NSAttributedString"];
    > NSMutableAttributedString *mats = [[NSMutableAttributedString alloc]
    > initWithString:@"I am an NSMutableAttributedString"];
    > if ([str respondsToSelector: @selector(appendString:)]) {
    > NSLog(@"Should not happen!");
    > NSLog(@"[str class] = %@",[str class]);
    > }
    > if ([mstr respondsToSelector: @selector(appendString:)]) {
    > NSLog(@"Ok for NSMutableString!");
    > NSLog(@"[mstr class] = %@",[mstr class]);
    > }
    > if ([array respondsToSelector: @selector(addObject:)]) {
    > NSLog(@"Should not happen!");
    > NSLog(@"[array class] = %@",[array class]);
    > }
    > if ([marray respondsToSelector: @selector(addObject:)]) {
    > NSLog(@"Ok for NSMutableArray!");
    > NSLog(@"[mstr class] = %@",[marray class]);
    > }
    > if ([set respondsToSelector: @selector(addObject:)]) {
    > NSLog(@"Should not happen!");
    > NSLog(@"[set class] = %@",[set class]);
    > }
    > if ([mset respondsToSelector: @selector(addObject:)]) {
    > NSLog(@"Ok for NSMutableSet!");
    > NSLog(@"[mset class] = %@",[mset class]);
    > }
    > if ([ats respondsToSelector: @selector(appendAttributedString:)]) {
    > NSLog(@"Should not happen!");
    > NSLog(@"[ats class] = %@",[ats class]);
    > }
    >
    > if ([mats respondsToSelector: @selector(appendAttributedString:)]) {
    > NSLog(@"Ok for NSMutableSet!");
    > NSLog(@"[mats class] = %@",[mats class]);
    > }
    >
    > [pool release];
    > return 0;
    > }

    Here the results:
    > Current language:  auto; currently objective-c
    > 2004-07-08 14:00:33.366 AAA[2308] Should not happen!
    > 2004-07-08 14:00:34.448 AAA[2308] [str class] = NSCFString
    > 2004-07-08 14:00:37.457 AAA[2308] Ok for NSMutableString!
    > 2004-07-08 14:00:38.553 AAA[2308] [mstr class] = NSCFString
    > 2004-07-08 14:00:40.669 AAA[2308] Should not happen!
    > 2004-07-08 14:00:45.180 AAA[2308] [array class] = NSCFArray
    > 2004-07-08 14:00:55.527 AAA[2308] Ok for NSMutableArray!
    > 2004-07-08 14:00:56.765 AAA[2308] [mstr class] = NSCFArray
    > 2004-07-08 14:00:59.753 AAA[2308] Should not happen!
    > 2004-07-08 14:01:00.808 AAA[2308] [set class] = NSCFSet
    > 2004-07-08 14:01:10.595 AAA[2308] Ok for NSMutableSet!
    > 2004-07-08 14:01:12.655 AAA[2308] [mset class] = NSCFSet
    > 2004-07-08 14:01:21.643 AAA[2308] Ok for NSMutableSet!
    > 2004-07-08 14:01:42.514 AAA[2308] [mats class] =
    > NSConcreteMutableAttributedString
    > (gdb)

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Jul 8, 2004, at 3:40 PM, Scott Stevenson wrote:

    >
    > On Jul 8, 2004, at 1:21 PM, Gerd Knops wrote:
    >
    >> That's beside the point. And the fact that it returns true goes to
    >> show how perverted this situation really is... Basically there is an
    >> object that claims to be an NSMutableString, and then complains
    >> bitterly if you treat it as such. OOP at it's worst!
    >
    > Eh, not sure I agree with that. I haven't followed this thread
    > closely, but every language/framework has its own idea of how to
    > implement the ideals of OO ideals.
    >
    > One of the themes in Cocoa is "loosely coupled". Personally, I don't
    > think you should worry about the implementation details of the object
    > you acquire from another source. That's somewhat heavy handed.

    Introspection has been part of (and in IMHO a strength of) the
    Objective-C runtime since the beginning. In many situations it has
    tremendous benefits, for example in modular software or wherever
    delegation is involved.

    > If you need a mutable string, take the string object and do a
    > -mutableCopy. If you need to apply changes back to the source, send
    > the new object to the appropriate setter.
    >
    Agreed.

    > I think you could argue that this is a better approach because it
    > gives the source of the original string the opportunity to do
    > additional work when changes are made to the string. Changing the
    > contents out from under the source means it may not be able to keep
    > something else in sync easily.
    >
    > I do, however, agree that if something says it can respond to a
    > selector, it should.
    >
    And that it shouldn't pretend to be class X when it really isn't. And
    that is the point. If I get an object, I should NOT have to worry about
    how it came into existence. I should be able to rely on it behaving
    like an object of the class it is pretending to be a member of. When it
    doesn't, we break some of the fundamental ideas of OOP, and end up with
    action on a distance. And this counts doubly so for such fundamental
    Objects like String, Number, Array and Dictionary.

    Gerd

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • Fabien,

    Essentially its a no-op. The problem is that when you create an
    instance of a string, the library is returning a subclass on you - or
    making NSCFString 'poseAsClass' NSString. Thus if you ask an NSString
    what class it is, it will happily tell you that it is an NSCFString
    which of course responds to all the methods of NSString and
    NSMutableString.

    The only problem is that to you they are NSString or NSMutableString so
    you are expecting these things to respond that they are those things.
    But they are not. Hence the issue. For those who care, here's the
    class-dump of this thing.

    Cheers,

    /a

    @interface NSCFString : NSMutableString
    {
    }

    - (id)retain;
    - (oneway void)release;
    - (unsigned int)retainCount;
    - (unsigned int)hash;
    - (unsigned int)length;
    - (unsigned short)characterAtIndex:(unsigned int)fp8;
    - (void)getCharacters:(unsigned short *)fp8 range:(struct _NSRange)fp12;
    - (const unsigned short *)_fastCharacterContents;
    - (const char *)_fastCStringContents:(BOOL)fp8;
    - (const char *)cString;
    - (const char *)UTF8String;
    - (unsigned int)cStringLength;
    - (id)substringWithRange:(struct _NSRange)fp8;
    - (BOOL)isEqual:(id)fp8;
    - (BOOL)isEqualToString:(id)fp8;
    - (BOOL)hasPrefix:(id)fp8;
    - (BOOL)hasSuffix:(id)fp8;
    - (void)getLineStart:(unsigned int *)fp8 end:(unsigned int *)fp12
    contentsEnd:(unsigned int *)fp16 forRange:(struct _NSRange)fp20;
    - (id)copyWithZone:(struct _NSZone *)fp8;
    - (id)mutableCopyWithZone:(struct _NSZone *)fp8;
    - (unsigned int)fastestEncoding;
    - (unsigned int)smallestEncoding;
    - (Class)classForCoder;
    - (BOOL)_isCString;
    - (void)replaceCharactersInRange:(struct _NSRange)fp8
    withString:(id)fp16;
    - (void)insertString:(id)fp8 atIndex:(unsigned int)fp12;
    - (void)appendString:(id)fp8;
    - (void)deleteCharactersInRange:(struct _NSRange)fp8;
    - (void)appendFormat:(id)fp8;
    - (void)setString:(id)fp8;
    - (void)appendCharacters:(const unsigned short *)fp8 length:(unsigned
    int)fp12;
    - (unsigned int)replaceOccurrencesOfString:(id)fp8 withString:(id)fp12
    options:(unsigned int)fp16 range:(struct _NSRange)fp20;

    @end

    On Jul 8, 2004, at 4:10 PM, Fabien Roy wrote:

    > Time to file a bug I guess.
    > It seems that most of the CF based classes are implemented as one
    > class for their mutable and non-mutable parts.
    > NSAttributedString and NSMutableAttributedString which are non CF
    > based do not show that stupid behavior. Hope that Tiger will fix this!
    > And because of the NDA I will have no way to tell :-(
    >
    > Here a sample code:
    >
    >> #import <Foundation/Foundation.h>
    >>
    >> int main (int argc, const char * argv[]) {
    >> NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    >>
    >> // insert code here...
    >> NSString *str = [NSString stringWithFormat:@"Hello %d times",3];
    >> NSMutableString *mstr = [[[NSMutableString alloc] init] autorelease];
    >> NSArray *array = [NSArray
    >> arrayWithObjects:@"one",@"two",@"three",nil];
    >> NSMutableArray *marray = [[[NSMutableArray alloc] init] autorelease];
    >> NSSet *set = [NSSet setWithObjects:@"one",@"two",@"three",nil];
    >> NSMutableSet *mset = [[[NSMutableSet alloc] init] autorelease];
    >> NSAttributedString *ats = [[NSAttributedString alloc]
    >> initWithString:@"I am an NSAttributedString"];
    >> NSMutableAttributedString *mats = [[NSMutableAttributedString alloc]
    >> initWithString:@"I am an NSMutableAttributedString"];
    >> if ([str respondsToSelector: @selector(appendString:)]) {
    >> NSLog(@"Should not happen!");
    >> NSLog(@"[str class] = %@",[str class]);
    >> }
    >> if ([mstr respondsToSelector: @selector(appendString:)]) {
    >> NSLog(@"Ok for NSMutableString!");
    >> NSLog(@"[mstr class] = %@",[mstr class]);
    >> }
    >> if ([array respondsToSelector: @selector(addObject:)]) {
    >> NSLog(@"Should not happen!");
    >> NSLog(@"[array class] = %@",[array class]);
    >> }
    >> if ([marray respondsToSelector: @selector(addObject:)]) {
    >> NSLog(@"Ok for NSMutableArray!");
    >> NSLog(@"[mstr class] = %@",[marray class]);
    >> }
    >> if ([set respondsToSelector: @selector(addObject:)]) {
    >> NSLog(@"Should not happen!");
    >> NSLog(@"[set class] = %@",[set class]);
    >> }
    >> if ([mset respondsToSelector: @selector(addObject:)]) {
    >> NSLog(@"Ok for NSMutableSet!");
    >> NSLog(@"[mset class] = %@",[mset class]);
    >> }
    >> if ([ats respondsToSelector: @selector(appendAttributedString:)]) {
    >> NSLog(@"Should not happen!");
    >> NSLog(@"[ats class] = %@",[ats class]);
    >> }
    >>
    >> if ([mats respondsToSelector: @selector(appendAttributedString:)]) {
    >> NSLog(@"Ok for NSMutableSet!");
    >> NSLog(@"[mats class] = %@",[mats class]);
    >> }
    >>
    >> [pool release];
    >> return 0;
    >> }
    >
    > Here the results:
    >> Current language:  auto; currently objective-c
    >> 2004-07-08 14:00:33.366 AAA[2308] Should not happen!
    >> 2004-07-08 14:00:34.448 AAA[2308] [str class] = NSCFString
    >> 2004-07-08 14:00:37.457 AAA[2308] Ok for NSMutableString!
    >> 2004-07-08 14:00:38.553 AAA[2308] [mstr class] = NSCFString
    >> 2004-07-08 14:00:40.669 AAA[2308] Should not happen!
    >> 2004-07-08 14:00:45.180 AAA[2308] [array class] = NSCFArray
    >> 2004-07-08 14:00:55.527 AAA[2308] Ok for NSMutableArray!
    >> 2004-07-08 14:00:56.765 AAA[2308] [mstr class] = NSCFArray
    >> 2004-07-08 14:00:59.753 AAA[2308] Should not happen!
    >> 2004-07-08 14:01:00.808 AAA[2308] [set class] = NSCFSet
    >> 2004-07-08 14:01:10.595 AAA[2308] Ok for NSMutableSet!
    >> 2004-07-08 14:01:12.655 AAA[2308] [mset class] = NSCFSet
    >> 2004-07-08 14:01:21.643 AAA[2308] Ok for NSMutableSet!
    >> 2004-07-08 14:01:42.514 AAA[2308] [mats class] =
    >> NSConcreteMutableAttributedString
    >> (gdb)
    >
    >
    >

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • This is huge regression from OPENSTEP. Even if that returned class says
    that it responds to all methods of NSString and NSMutableString how in
    the hell is when you try to execute a mutable method on a non mutable
    instance of NSCFString the method crashes! So there must be a way that
    this class KNOWS that this instance is immutable.
    I would like to see the technical justification of this design.

    Fabien

    I was not convince that CF was a good move for Apple. Now I think that
    it was a STUPID move.

    On Jul 9, 2004, at 9:05 AM, Alberto Ricart wrote:

    > Fabien,
    >
    > Essentially its a no-op. The problem is that when you create an
    > instance of a string, the library is returning a subclass on you - or
    > making NSCFString 'poseAsClass' NSString. Thus if you ask an NSString
    > what class it is, it will happily tell you that it is an NSCFString
    > which of course responds to all the methods of NSString and
    > NSMutableString.
    >
    > The only problem is that to you they are NSString or NSMutableString
    > so you are expecting these things to respond that they are those
    > things. But they are not. Hence the issue. For those who care, here's
    > the class-dump of this thing.
    >
    > Cheers,
    >
    > /a
    >
    >
    > @interface NSCFString : NSMutableString
    > {
    > }
    >
    > - (id)retain;
    > - (oneway void)release;
    > - (unsigned int)retainCount;
    > - (unsigned int)hash;
    > - (unsigned int)length;
    > - (unsigned short)characterAtIndex:(unsigned int)fp8;
    > - (void)getCharacters:(unsigned short *)fp8 range:(struct
    > _NSRange)fp12;
    > - (const unsigned short *)_fastCharacterContents;
    > - (const char *)_fastCStringContents:(BOOL)fp8;
    > - (const char *)cString;
    > - (const char *)UTF8String;
    > - (unsigned int)cStringLength;
    > - (id)substringWithRange:(struct _NSRange)fp8;
    > - (BOOL)isEqual:(id)fp8;
    > - (BOOL)isEqualToString:(id)fp8;
    > - (BOOL)hasPrefix:(id)fp8;
    > - (BOOL)hasSuffix:(id)fp8;
    > - (void)getLineStart:(unsigned int *)fp8 end:(unsigned int *)fp12
    > contentsEnd:(unsigned int *)fp16 forRange:(struct _NSRange)fp20;
    > - (id)copyWithZone:(struct _NSZone *)fp8;
    > - (id)mutableCopyWithZone:(struct _NSZone *)fp8;
    > - (unsigned int)fastestEncoding;
    > - (unsigned int)smallestEncoding;
    > - (Class)classForCoder;
    > - (BOOL)_isCString;
    > - (void)replaceCharactersInRange:(struct _NSRange)fp8
    > withString:(id)fp16;
    > - (void)insertString:(id)fp8 atIndex:(unsigned int)fp12;
    > - (void)appendString:(id)fp8;
    > - (void)deleteCharactersInRange:(struct _NSRange)fp8;
    > - (void)appendFormat:(id)fp8;
    > - (void)setString:(id)fp8;
    > - (void)appendCharacters:(const unsigned short *)fp8 length:(unsigned
    > int)fp12;
    > - (unsigned int)replaceOccurrencesOfString:(id)fp8 withString:(id)fp12
    > options:(unsigned int)fp16 range:(struct _NSRange)fp20;
    >
    > @end
    >
    >
    >
    >
    > On Jul 8, 2004, at 4:10 PM, Fabien Roy wrote:
    >
    >> Time to file a bug I guess.
    >> It seems that most of the CF based classes are implemented as one
    >> class for their mutable and non-mutable parts.
    >> NSAttributedString and NSMutableAttributedString which are non CF
    >> based do not show that stupid behavior. Hope that Tiger will fix
    >> this! And because of the NDA I will have no way to tell :-(
    >>
    >> Here a sample code:
    >>
    >>> #import <Foundation/Foundation.h>
    >>>
    >>> int main (int argc, const char * argv[]) {
    >>> NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    >>>
    >>> // insert code here...
    >>> NSString *str = [NSString stringWithFormat:@"Hello %d times",3];
    >>> NSMutableString *mstr = [[[NSMutableString alloc] init]
    >>> autorelease];
    >>> NSArray *array = [NSArray
    >>> arrayWithObjects:@"one",@"two",@"three",nil];
    >>> NSMutableArray *marray = [[[NSMutableArray alloc] init]
    >>> autorelease];
    >>> NSSet *set = [NSSet setWithObjects:@"one",@"two",@"three",nil];
    >>> NSMutableSet *mset = [[[NSMutableSet alloc] init] autorelease];
    >>> NSAttributedString *ats = [[NSAttributedString alloc]
    >>> initWithString:@"I am an NSAttributedString"];
    >>> NSMutableAttributedString *mats = [[NSMutableAttributedString
    >>> alloc] initWithString:@"I am an NSMutableAttributedString"];
    >>> if ([str respondsToSelector: @selector(appendString:)]) {
    >>> NSLog(@"Should not happen!");
    >>> NSLog(@"[str class] = %@",[str class]);
    >>> }
    >>> if ([mstr respondsToSelector: @selector(appendString:)]) {
    >>> NSLog(@"Ok for NSMutableString!");
    >>> NSLog(@"[mstr class] = %@",[mstr class]);
    >>> }
    >>> if ([array respondsToSelector: @selector(addObject:)]) {
    >>> NSLog(@"Should not happen!");
    >>> NSLog(@"[array class] = %@",[array class]);
    >>> }
    >>> if ([marray respondsToSelector: @selector(addObject:)]) {
    >>> NSLog(@"Ok for NSMutableArray!");
    >>> NSLog(@"[mstr class] = %@",[marray class]);
    >>> }
    >>> if ([set respondsToSelector: @selector(addObject:)]) {
    >>> NSLog(@"Should not happen!");
    >>> NSLog(@"[set class] = %@",[set class]);
    >>> }
    >>> if ([mset respondsToSelector: @selector(addObject:)]) {
    >>> NSLog(@"Ok for NSMutableSet!");
    >>> NSLog(@"[mset class] = %@",[mset class]);
    >>> }
    >>> if ([ats respondsToSelector: @selector(appendAttributedString:)]) {
    >>> NSLog(@"Should not happen!");
    >>> NSLog(@"[ats class] = %@",[ats class]);
    >>> }
    >>>
    >>> if ([mats respondsToSelector: @selector(appendAttributedString:)]) {
    >>> NSLog(@"Ok for NSMutableSet!");
    >>> NSLog(@"[mats class] = %@",[mats class]);
    >>> }
    >>>
    >>> [pool release];
    >>> return 0;
    >>> }
    >>
    >> Here the results:
    >>> Current language:  auto; currently objective-c
    >>> 2004-07-08 14:00:33.366 AAA[2308] Should not happen!
    >>> 2004-07-08 14:00:34.448 AAA[2308] [str class] = NSCFString
    >>> 2004-07-08 14:00:37.457 AAA[2308] Ok for NSMutableString!
    >>> 2004-07-08 14:00:38.553 AAA[2308] [mstr class] = NSCFString
    >>> 2004-07-08 14:00:40.669 AAA[2308] Should not happen!
    >>> 2004-07-08 14:00:45.180 AAA[2308] [array class] = NSCFArray
    >>> 2004-07-08 14:00:55.527 AAA[2308] Ok for NSMutableArray!
    >>> 2004-07-08 14:00:56.765 AAA[2308] [mstr class] = NSCFArray
    >>> 2004-07-08 14:00:59.753 AAA[2308] Should not happen!
    >>> 2004-07-08 14:01:00.808 AAA[2308] [set class] = NSCFSet
    >>> 2004-07-08 14:01:10.595 AAA[2308] Ok for NSMutableSet!
    >>> 2004-07-08 14:01:12.655 AAA[2308] [mset class] = NSCFSet
    >>> 2004-07-08 14:01:21.643 AAA[2308] Ok for NSMutableSet!
    >>> 2004-07-08 14:01:42.514 AAA[2308] [mats class] =
    >>> NSConcreteMutableAttributedString
    >>> (gdb)
    >>
    >>
    >>
    >

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • On Jul 9, 2004, at 7:27 PM, Fabien Roy wrote:

    > This is huge regression from OPENSTEP. Even if that returned class
    > says that it responds to all methods of NSString and NSMutableString
    > how in the hell is when you try to execute a mutable method on a non
    > mutable instance of NSCFString the method crashes! So there must be a
    > way that this class KNOWS that this instance is immutable.
    > I would like to see the technical justification of this design.

    What about speed?

    This is a well known fact that the "type" returned by the AppKit and
    Foundation are not necessarily exactly the "type" declared in the
    prototype.

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • Take an old 68040 NeXT machine and see that some operations are still
    snappy!
    I don't care about the type but an object pretending to respond to a
    method and would crash when applying that method is just useless. Its
    like having a really fast car with really bad brakes or steering. And
    talking about speed, I was told that some the early CF classes did
    regress from the OPENSTEP ones, i.e. their algorithm were in "N^2"
    where the original implementation was on "N log N".

    Fabien
    On Jul 9, 2004, at 10:37 AM, Stéphane Sudre wrote:

    > What about speed?
    >
    > This is a well known fact that the "type" returned by the AppKit and
    > Foundation are not necessarily exactly the "type" declared in the
    > prototype.

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
  • Speed? My take is that this depends on the algorithm used, not on how
    one class implements (some/all) the functionality of another. Aside
    from the messaging overhead (which makes me, a programmer, speedier),
    we are talking about 'C' code. If you need it faster, you can always
    tweak your algorithm, write plain C code, or take a dive into assembly.

    Regardless of speed, I do have a problem with NSString and
    NSMutableStrings not being what they claim to be. If you told me these
    classes came from an "NSStringFactory" which returned any
    implementation appropriate for the task/interface I would be happy
    because I would known that the type is really based on some interface
    and the actual impl is not important, but that is not what is happening
    here.

    In the end this is all kind of 'pointless'. As I don't think they are
    going to revamp foundation to fix how ObjC handles respondsToSelector.
    AppKit is second to the other apis and this is just another hint/result
    of this.

    And yes, CF was not a good move because it introduced inconsistencies
    and weird integration points.  However, if it wasn't for these types of
    things, we probably wouldn't have what we have. As for sure Steve
    wasn't going to make the same mistake twice of having an app-less nice
    environment.

    I think the solution is simply type these things as id, and if you need
    to edit it, mutableCopy it, and do your thing. Let the library deal
    with how quickly it needs to copy the bytes (I am sure altivec comes
    really handy for these).

    Cheers,

    /a

    On Jul 9, 2004, at 12:37 PM, Stéphane Sudre wrote:

    >
    > On Jul 9, 2004, at 7:27 PM, Fabien Roy wrote:
    >
    >> This is huge regression from OPENSTEP. Even if that returned class
    >> says that it responds to all methods of NSString and NSMutableString
    >> how in the hell is when you try to execute a mutable method on a non
    >> mutable instance of NSCFString the method crashes! So there must be a
    >> way that this class KNOWS that this instance is immutable.
    >> I would like to see the technical justification of this design.
    >
    > What about speed?
    >
    > This is a well known fact that the "type" returned by the AppKit and
    > Foundation are not necessarily exactly the "type" declared in the
    > prototype.
    >
    > _______________________________________________
    > MacOSX-dev mailing list
    > <MacOSX-dev...>
    > http://www.omnigroup.com/mailman/listinfo/macosx-dev
    >
    >

    _______________________________________________
    MacOSX-dev mailing list
    <MacOSX-dev...>
    http://www.omnigroup.com/mailman/listinfo/macosx-dev
previous month july 2004 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31  
Go to today