Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSHTTPURLResponse allHeaderFields case sensitivity

How come that -[[NSHTTPURLResponse allHeaderFields] valueForKey:] is case insensitive, while valueForKey: for manually created NSDictionary is not?

Both seems to be instances of NSCFDictionary;

Poking the first one with variation of, let's say, Content-Type, content-type, ConTEnt-TYPe returns the same value

Manually created NSDictionary *a = @{ @"content-type" : @"pillows" } returns nil for any spelling other then lowercase "content-type"

Edit Turns out this behavior can be easily achieved when dropping down to core foundation level: https://gist.github.com/steipete/7739473

like image 410
Sash Zats Avatar asked Oct 03 '22 07:10

Sash Zats


1 Answers

They aren't both NSCFDictionary

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
{
    NSDictionary *dictionary1 = [(NSHTTPURLResponse*)response allHeaderFields];
    NSDictionary *dictionary2 = [NSDictionary dictionaryWithObjects:[dictionary1 allValues] forKeys:[dictionary1 allKeys]];
}

in lldb:

(lldb) po [dictionary2 class]
__NSDictionaryI
(lldb) po [dictionary1 class]
__NSCFDictionary

and seems __NSCFDictionary keys are actually case-insensitive 0_0.
Class inheritance looks so for __NSCFDictionary: __NSCFDictinary <-- NSMutableDictionary <-- NSDictionary.
For __NSDictionaryI: __NSDictionaryI <-- NSDictionary
Check debug output:

(lldb) po [dictionary1 superclass]
NSMutableDictionary
(lldb) po [[dictionary1 superclass] superclass]
NSDictionary
(lldb) po [dictionary2 superclass]
NSDictionary

I also created

NSMutableDictionary *dictionary3 = [dictionary2 mutableCopy];

and tried

(lldb) po [dictionary3 class]
__NSDictionaryM
(lldb) po [[dictionary3 class] superclass]
NSMutableDictionary
(lldb) po [[[dictionary3 class] superclass] superclass]
NSDictionary
(lldb) po dictionary3[@"date"]
 nil
(lldb) po dictionary3[@"Date"]
Sun, 01 Dec 2013 13:35:22 GMT

So it seems like only __NSCFDictionary subclass of NSMutableDictionary has case-insensitive keys.
And.. i think it's made through -objectForKey: -setObject:forKey: implementation. Not through custom NSString's.
Moreover, this __NSCFDictionary is immutable subclass of NSMutableDictionary.. it overrides setObject:forKey: to throw exception.
So the short answer is:
It's done by Apple through some private Foundation dictionary class.

like image 54
Petro Korienev Avatar answered Oct 13 '22 10:10

Petro Korienev