RS: Reply about NSObject members class, isMemberOfClass, isKindOfClass

  • Mike Abdullah,
    The reason I need to know whether an object is a mutable array is
    that in a current program I have bugs involving APPARENTLY creating
    NSMutableArrays that turn out not to be mutable, and I need help to
    track down where the bugs are.

    I have since written a predicate that tests an object for
    mutablearrayness, based on a method (removeLastObject) that is (per
    last release of Xcode) apparently unique to NSMutableArray, plus the
    try/catch/finally hack.
    --RS

    Fritz Anderson,
    I wasn't aware of isKindOfClass, but I'll give it a shot.
    --RS
    --RS

    Chris Suter,
    Your suggestion
    return ((unsigned short *)self)[2] & 3 ? YES : NO;
    is amazingly terse -- if difficult to understand. I wonder whether it
    is stable against possible future changes by Apple in the structures
    underlying Objective-C.
    --RS

    BTW, nobody addressed my question about why the <class> and <
    isMemberOfClass> methods behave the way they do. Is my copy of Xcode
    broken?
    --RS
    ------------------------------------------

    On Sep 7, 2007, at 09:49 , <cocoa-dev-request...> wrote:

    > Message: 3
    > Date: Fri, 7 Sep 2007 04:51:29 -0600
    > From: Roland Silver <rollos...>
    > Subject: RS: NSObject members class and isMemberOfClass
    >
    > While attempting to find a way to determine if an object ostensibly
    > created as an NSMutableArray really is (I can't change it), I wrote
    > this code:
    >
    > #import <Cocoa/Cocoa.h>
    >
    > @interface foo : NSObject {}
    > @end
    >
    > @implementation foo
    > -(void)awakeFromNib {
    > NSArray* arr = [NSArray array];
    > NSMutableArray* mut = [NSMutableArray array];
    > BOOL test1, test2, test3, test4, test5, test6, test7, test8, test9;
    > test1 = ([arr isMemberOfClass:[NSArray class]]);
    > test2 = ([mut isMemberOfClass:[NSArray class]]);
    > test3 = ([arr isMemberOfClass:[NSMutableArray class]]);
    > test4 = ([mut isMemberOfClass:[NSMutableArray class]]);
    > test5 = ([mut class] == [NSMutableArray class]);
    > test6 = ([mut class] == [arr class]);
    > test7 = ([NSArray class] == [NSArray class]);
    > test8 = ([NSMutableArray class] == [NSMutableArray class]);
    > test9 = ([NSArray class] == [NSMutableArray class]);
    > NSString* arrStr = [arr className];
    > NSString* mutStr = [mut className];
    > int mutCount1 = [mut count];
    > [mut addObject:@"foo"];
    > int mutCount2 = [mut count];
    > } //end awakeFromNib
    > @end
    >
    > When I run it under debugging with a breakpoint on the right-curly
    > line, the values of the variables are:
    > test1  NO
    > test2  NO
    > test3  NO
    > test4  NO
    > test5  NO
    > test6  YES
    > test7  YES
    > test8  YES
    > test9  NO
    > arrStr NSCFArray
    > mutStr NSCFArray
    > mutCount1  0
    > mutCount2  1
    >
    > which don't make sense to me.
    >
    > How are the methods <class> and <isMemberOfClass> supposed to work?
    > How can I determine if an object ostensibly created as an
    > NSMutableArray really is?

    ------------------------------------------

    > Message: 5
    > Date: Fri, 7 Sep 2007 12:09:46 +0100
    > From: Mike Abdullah <cocoadev...>
    > Subject: Re: RS: NSObject members class and isMemberOfClass
    >
    > OK, well as it says in the docs, NSArray and NSMutableArray are
    > actually what is known as a class cluster. They are privately
    > subclassed by Cocoa in various ways. e.g. NSCFArray.
    >
    > However, this shouldn't matter to you, it is an implementation
    > detail. So the question that really matters is why you seem to need
    > to know this? If you ask Cocoa to create a mutable array, it will,
    > and you don't need to know or care about the actual class.
    >
    > Mike.
    >
    > ------------------------------------------
    >
    > Message: 9
    > Date: Fri, 7 Sep 2007 07:58:04 -0500
    > From: Fritz Anderson <fritza...>
    > Subject: Re: RS: NSObject members class and isMemberOfClass
    >
    > I concur with Mike Abdullah's point that explicit tests of class
    > membership raise a presumption that something is wrong with the
    > design.
    >
    > But why are you using isMemberOfClass: instead of isKindOfClass:?
    >
    > — F
    >
    > ------------------------------------------
    >
    > Message: 10
    > Date: Fri, 7 Sep 2007 14:15:42 +0100
    > From: "Finlay Dobbie" <finlay.dobbie...>
    > Subject: Re: RS: NSObject members class and isMemberOfClass
    >
    > On 07/09/2007, Mike Abdullah <cocoadev...> wrote:
    >> OK, well as it says in the docs, NSArray and NSMutableArray are
    >> actually what is known as a class cluster. They are privately
    >> subclassed by Cocoa in various ways. e.g. NSCFArray.
    >>
    >> However, this shouldn't matter to you, it is an implementation
    >> detail. So the question that really matters is why you seem to need
    >> to know this? If you ask Cocoa to create a mutable array, it will,
    >> and you don't need to know or care about the actual class.
    >
    > Well, it is slightly semantically broken - you ask for an NSArray and
    > you get an immutable instance of something which claims to be a
    > subclass of NSMutableArray back.
    >
    > There isn't any supported way of determining if an array is mutable or
    > not. You probably could do it using undocumented private
    > CoreFoundation functions, but you shouldn't really need to. If you
    > have an array and you need to modify it, and you're not sure if it's
    > mutable or not, make a mutable copy. You might want to do this anyway,
    > since the person that handed you the array might not want it to be
    > modified underneath them. Or if they do, say that you require a
    > mutable array, and assume that it will be mutable.
    >
    > -- Finlay
    >
    > ------------------------------------------
    >
    > Message: 13
    > Date: Sat, 8 Sep 2007 00:17:16 +1000
    > From: Chris Suter <chris...>
    > Subject: Re: RS: NSObject members class and isMemberOfClass
    >
    >> There isn't any supported way of determining if an array is
    >> mutable or
    >> not. You probably could do it using undocumented private
    >> CoreFoundation functions, but you shouldn't really need to.
    >
    > There are no private functions in CoreFoundation that you can use.
    > For purely academic purposes (not to be used in production code) the
    > following will tell you if an array happens to be mutable.
    >
    > @interface NSArray (IsMutable)
    >
    > - (BOOL)isMutable;
    >
    > @end
    >
    > @implementation NSArray (IsMutable)
    >
    > - (BOOL)isMutable
    > {
    > return ((unsigned short *)self)[2] & 3 ? YES : NO;
    > }
    >
    > @end
    >
    > - Chris
  • On Sep 7, 2007, at 4:04 PM, Roland Silver wrote:

    > The reason I need to know whether an object is a mutable array is
    > that in a current program I have bugs involving APPARENTLY creating
    > NSMutableArrays that turn out not to be mutable, and I need help to
    > track down where the bugs are.
    >
    > I have since written a predicate that tests an object for
    > mutablearrayness, based on a method (removeLastObject) that is (per
    > last release of Xcode) apparently unique to NSMutableArray, plus the
    > try/catch/finally hack.

    Xcode has nothing to do with the methods that NSMutableArray
    supports.  Xcode is just the IDE; the frameworks that make up Mac OS X
    are what actually contain all of the various classes.

    In any case, it should never be necessary to check whether an array is
    mutable or immutable.  The method signature that you get the object
    from will tell you how you should treat it; for example, the result of
    a method declared as returning an NSArray should never be treated as
    an NSMutableArray.  Similarly, the signature of a method that you're
    passing an object to will tell you how it's going to treat the object;
    for example, a method that takes an NSMutableArray parameter should
    never be passed an NSArray.

    One common case where people get tripped up is -copy versus -
    mutableCopy.  They expect sending -copy to an NSMutableArray to return
    an NSMutableArray; however, the result will actually be an NSArray.
    You need to explicitly ask collections to perform mutable copies by
    sending them -mutableCopy.

      -- Chris
  • On 8 Sep 2007, at 08:04, <cocoa-dev-request...> wrote:

    >
    > On Sep 7, 2007, at 4:04 PM, Roland Silver wrote:
    >
    >> The reason I need to know whether an object is a mutable array is
    >> that in a current program I have bugs involving APPARENTLY creating
    >> NSMutableArrays that turn out not to be mutable, and I need help to
    >> track down where the bugs are.
    >
    > In any case, it should never be necessary to check whether an array is
    > mutable or immutable.  The method signature that you get the object
    > from will tell you how you should treat it; for example, the result of
    > a method declared as returning an NSArray should never be treated as
    > an NSMutableArray.

    I have a method which gets an NSArray, but I know that sometimes it
    really gets supplied with a mutable thing.

    This method needs to do something with the array. So it would like to
    do:
    if ( ![myArray isMutable] ) myArray = [myArray mutableCopy];
    As you said, it is not *necessary* to check the mutablity of myArray
    - but it cleary would be more efficient.

    Kind regards,

    Gerriet.
  • OK, now that makes more sense. But you have to ask yourself whether
    the extra effort is really worth it. What you're doing here is to try
    and break outside the normal conventions for object-oriented
    programming for a tiny performance gain. Write your code to treat the
    array as immutable regardless and then if you run into performance
    problems consider an optimisation such as this.

    Also, your code below is likely to leak as myArray was probably
    originally autoreleased. Instead try:

    > if ( ![myArray isMutable] ) myArray = [[myArray mutableCopy]
    > autorelease];

    Mike.

    On 10 Sep 2007, at 13:03, Gerriet M. Denkmann wrote:

    >
    > On 8 Sep 2007, at 08:04, <cocoa-dev-request...> wrote:
    >
    >>
    >> On Sep 7, 2007, at 4:04 PM, Roland Silver wrote:
    >>
    >>> The reason I need to know whether an object is a mutable array is
    >>> that in a current program I have bugs involving APPARENTLY creating
    >>> NSMutableArrays that turn out not to be mutable, and I need help to
    >>> track down where the bugs are.
    >>
    >> In any case, it should never be necessary to check whether an
    >> array is
    >> mutable or immutable.  The method signature that you get the object
    >> from will tell you how you should treat it; for example, the
    >> result of
    >> a method declared as returning an NSArray should never be treated as
    >> an NSMutableArray.
    >
    > I have a method which gets an NSArray, but I know that sometimes it
    > really gets supplied with a mutable thing.
    >
    > This method needs to do something with the array. So it would like
    > to do:
    > if ( ![myArray isMutable] ) myArray = [myArray mutableCopy];
    > As you said, it is not *necessary* to check the mutablity of
    > myArray - but it cleary would be more efficient.
    >
    > Kind regards,
    >
    > Gerriet.
previous month september 2007 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
Go to today