Re: case-insensitive NSDictionary
Re: case-insensitive NSDictionary
- Subject: Re: case-insensitive NSDictionary
- From: Michael Ash <email@hidden>
- Date: Mon, 16 Mar 2009 12:03:10 -0400
On Mon, Mar 16, 2009 at 11:52 AM, Jean-Daniel Dupas
<email@hidden> wrote:
>
> Le 16 mars 09 à 16:37, Bill Bumgarner a écrit :
>
>> On Mar 16, 2009, at 7:05 AM, Dave DeLong wrote:
>>>
>>> You could swizzle the objectForKey: and setObject:forKey: methods with
>>> your own that just lowercase the passed in string and then call the actual
>>> methods with the new key.
>>
>> Wile certainly a creative solution, this suggestion is an 11 on the scale
>> of 1 to 10 of bad ideas. Even if it would work, which it won't because
>> NSDictionary -- as noted later -- is a class cluster.
>>
>> The swizzling would change the behavior of all NSDictionary instances.
>> I'd wager a rather large sum of money that the rest of the AppKit,
>> Foundation, CoreFoundation, CoreData, and any other framework that uses
>> NSDictionary instances would have at least one case where making all strings
>> suddenly case insensitive as keys would behave rather badly.
>>
>> Simple rule: Do Not Swizzle in Production Code.
>>
>> A solution to the OP's problem is to create a subclass of NSObject that
>> contains an NSString, implements the appropriate NSString like get/set
>> methods, and implements -hash and -isEqual: based on the -lowercase string
>> of the contained string. Make sure it implements the <NSCopying> protocol
>> so that it can be a key in a dictionary.
>>
>> You could also subclass NSString, if you want, and do -- effectively --
>> the same thing.
>>
>
> Subclassing NSString is probably not a so good idea, as this is a class
> cluster too and will require far more work than wrapping it.
Why does everybody think that subclassing a class cluster is hard?
When you want to retain the original capabilities of the class, you
just keep an instance of the original as an ivar. NSString has only
*two* primitive methods, so all you have to do is override those, plus
whatever functionality you want to change. Extremely easy. Here's an
NSString subclass that acts like an NSString except for hashing and
equality, in which case it uses the lowercase string for both:
@interface CaseInsensitiveString : NSString {
NSString *realString;
}
@end
@implementation CaseInsensitiveString
- (id)initWithString:(NSString *)aString {
if((self = [self init]))
realString = [aString copy];
return self;
}
- (void)dealloc {
[realString release];
[super dealloc];
}
- (NSUInteger)length {
return [realString length];
}
- (unichar)characterAtIndex:(NSUInteger)index {
return [realString characterAtIndex:index];
}
- (BOOL)isEqualToString:(NSString *)aString {
return [[realString lowercaseString] isEqualToString:[aString
lowercaseString]];
}
- (NSUInteger)hash {
return [[realString lowercaseString] hash];
}
@end
(Note that this relies on the undocumented implementation detail of
-isEqual: calling -isEqualToString: to do the real work. It's an
entirely logical and sensible thing for it to do, but it's not
guaranteed. If you use this for real, you should probably override
-isEqual: too, and of course I haven't tested this thing *at all* so
buyer beware.)
Mike
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden