I am new to Objective-C and I have no clue why this code is not working:
NSMutableDictionary *bookmarks = [NSMutableDictionary dictionaryWithCapacity:(NSUInteger) 4];
[bookmarks setObject:@"Stanford University" forKey:[NSURL URLWithString:(NSString *) @"http://www.stanford.edu"]];
[bookmarks setObject:@"Apple" forKey:[NSURL URLWithString:(NSString *) @"http://www.apple.com"]];
[bookmarks setObject:@"Berkeley" forKey:[NSURL URLWithString:(NSString *) @"http://www.berkeley.edu"]];
[bookmarks setObject:@"CS193P" forKey:[NSURL URLWithString:(NSString *) @"http://cs193p.stanford.edu"]];
NSEnumerator *browser = [bookmarks keyEnumerator];
id each;
NSURL *url;
while ((each = [browser nextObject])) {
url = [browser valueForKey:(NSString *)each];
NSLog(@"%@", [url absoluteURL]);
}
The error I get is:
2009-06-29 11:25:22.844 WhatATool[2102:10b] *** -[NSURL length]: unrecognized selector sent to instance 0x1072c0
2009-06-29 11:25:22.845 WhatATool[2102:10b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL length]: unrecognized selector sent to instance 0x1072c0'
Any help would be appreciated. Thanks.
A key is what you use to access an object in the dictionary. You have your keys and objects reversed on every line you call -[bookmarks setObject:... forKey...]
in the code. The problem in your case arises because you're trying to treat NSURL objects as NSString objects — [bookmarks objectForKey:(NSString *)each]
— and the dictionary is trying to get the length of the supposed string by calling -length
, which exists for NSString but not for NSURL.
If you're always constructing a dictionary with the same objects, consider using a more compact "varargs" constructor for NSDictionary
. (Note that the last comma-separated argument must be nil — see the related documentation) You can also use -[NSDictionary dictionaryWithObjects:forKeys:]
with two NSArray objects, containing the URLs and the bookmark names. (Incidentally, casting string literals as NSString*
to create an NSURL is completely unnecessary.)
NSDictionary *bookmarks = [NSDictionary dictionaryWithObjectsAndKeys:
[NSURL URLWithString:@"http://www.stanford.edu"],
@"Stanford University",
[NSURL URLWithString:@"http://www.apple.com"],
@"Apple",
[NSURL URLWithString:@"http://www.berkeley.edu"],
@"Berkeley",
[NSURL URLWithString:@"http://cs193p.stanford.edu"],
@"CS193P",
nil];
In addition, you have a lurking error that hasn't been mentioned yet: browser
is an NSEnumerator
, but you're calling valueForKey:
as if it were an NSDictionary
, rather than on bookmarks
. That will cause a similar crash for an unrecognized selector, too. (Even for dictionary objects, you should call -objectForKey:
instead; -valueForKey:
is used mostly for/by Cocoa Bindings, and does extra work you don't need. I realize it's confusing since we think in terms of "key-value pairs", but there it is...)
Finally, you can also simplify the enumeration code somewhat. (A for-in loop on an NSDictionary
enumerates its keys just like -keyEnumerator
would.)
Here's how I'd suggest doing the last part:
NSURL *url
for (NSString *key in bookmarks) {
url = [bookmarks objectForKey:key];
NSLog(@"%@", [url absoluteURL]);
}