2

I understand the difference between isKindOfClass: and isMemberOfClass: but I came across something I do not understand:

-(UIImage *)doSomething:(id)item 
{

    UIImage *image;

    if ([item isKindOfClass:[NSDictionary class]]) {
        NSDictionary *dictionary = item;
        NSData *data = [dictionary objectForKey:@"image"];
        image = [[UIImage alloc] initWithData:data];
    } else { // if item is UIImage
        image = item;
    }

    return image;
}

If I am using isKindOfClass in this context everything works as expected. If I use isMemberOfClass I get the following crash asking for the size of the image later:

-[__NSDictionaryI size]: unrecognized selector sent to instance 0x123456

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI size]: unrecognized selector sent to instance 0x123456'

I read other posts like this one but I couldn't find anything that would come closer.

Community
  • 1
  • 1
lukas_o
  • 3,776
  • 4
  • 34
  • 50
  • NSDictionary is a so called class cluster. It uses concrete subclasses (like __NSDictionaryI for immutable implementations) to abstract away implementation details. See https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/ClassCluster.html – HAS Jan 21 '15 at 14:46

1 Answers1

4

Yes they are different and their difference is documented. Using isKindOfClass: will return YES for subclasses whereas isMemberOfClass: won't. Since NSDictionary is a class cluster (uses private subclasses internally) will get different results when using the two (because the instance would be a private subclass (in your case __NSDictionaryI).

When using isMemberOfClass:, this is what happens in your case:

  1. The argument item is a private dictionary subclass
  2. Evaluating isMemberOfClass: returns NO
  3. The dictionary is assigned to a UIImage variable
  4. The UIImage variable is returned (but it really contains a dictionary)
  5. You try and use that "image" and when the system asks for the image size, the dictionary doesn't respond to size and throws an exception.
David Rönnqvist
  • 56,267
  • 18
  • 167
  • 205