iphonekeynsmutabledictionaryuicolorcopywithzone

Problem when using UIColor RGB black as a key in an NSMutableDictionary


I can set UIColor objects as keys in an NSMutableDictionary all day long and everything is fine and happy...

For instance:

[myDict setObject:foo forKey:[UIColor redColor]]; 

That works just fine... UNLESS I try to use the following:

UIColor *black = [[UIColor alloc] initWithRed:0 green:0 blue:0 alpha:1];
[myDict setObject:foo forKey:black];

That always gives me:

-[UIDeviceRGBColor copyWithZone:]: unrecognized selector sent to instance 0x691be80

The reasons for why I'm defining black in the RGB colorspace are unimportant to this question, just know that I must define it that way. What I don't understand is why is this and only this color causing me a problem, and why is it that the error is a copyWithZone error?

For the record, [UIColor blackColor] works as a key, but because it isn't an RGB colorspace it is not suitable for my application.


Solution

  • It looks like the better question is "why does every other UIColor instance work as a key"?

    Keys in an NSMutableDictionary "must conform to the NSCopying protocol". UIColor objects don't conform to that protocol per the documentation, so you're theoretically unable to use them as keys in a dictionary.

    In practice, I might guess that you're getting various concrete subclasses from a class cluster that's hidden by UIColor, and maybe some of them do, in fact, support NSCopying, but UIDeviceRGBColor does not seem to.

    You could wrap the UIColor object in a thin wrapper object that did support NSCopying, and override -isEqualTo: etc to get the comparisons to work correctly, and then use those wrappers in the dictionary.