Debugging NSDictionary和NSURL的Objective-C问题

Debugging NSDictionary和NSURL的Objective-C问题,debugging,nsstring,nsdictionary,nsurl,Debugging,Nsstring,Nsdictionary,Nsurl,我是Objective-C新手,我不知道为什么该代码不起作用: NSMutableDictionary *bookmarks = [NSMutableDictionary dictionaryWithCapacity:(NSUInteger) 4]; [bookmarks setObject:@"Stanford University" forKey:[NSURL URLWithString:(NSString *) @"http://www.stanford.edu"]]; [book

我是Objective-C新手,我不知道为什么该代码不起作用:

    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]);
}
我得到的错误是:

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'
任何帮助都将不胜感激。
谢谢。

您的书签词典初始化已反转:

[bookmarks setObject:@"Stanford University" forKey:[NSURL URLWithString:(NSString *) @"http://www.stanford.edu"]];
应该是:

[bookmarks setObject:[NSURL URLWithString:(NSString *) @"http://www.stanford.edu"] forKey:@"Stanford University"];
此外,还有一种更简单的枚举方法:

NSURL *url;
for ( NSString *each in [bookmarks allKeys] ) 
{
        url = [browser objectForKey:(NSString *)each];
        NSLog(@"%@", [url absoluteURL]);
}

您也可以通过[bookmarks allValues]枚举直接获取URL对象,而不是首先获取键(尽管您可能出于其他原因需要这些键)。

我认为您在获取URL时在while循环中引用了错误的变量(我认为应该使用
objectForKey:
选择器获取NSDictionary的值,而不是
valueForKey:
):

NSEnumerator*browser=[bookmarks keyEnumerator];
每个id;
NSURL*url;
而((每个=[浏览器下一个对象]){

url=[bookmarks objectForKey:(NSString*)each];//一个是用来访问字典中的对象。您在调用
的每一行上都有相反的键和对象-[bookmarks setObject:…forKey…]
在代码中。出现问题的原因是您试图将NSURL对象视为NSString对象-
[bookmarks objectForKey:(NSString*)each]
-词典试图通过调用
-length
获取假定字符串的长度,该字符串存在于NSString中,但不适用于NSURL

如果你总是用相同的对象构造一个字典,考虑使用一个更紧凑的“VARARGS”构造器用于<代码> NS字典> /COD>。(注意最后一个逗号分隔的参数必须是NIL-SED)。(顺便说一句,将字符串文本强制转换为
NSString*
,以创建NSURL完全没有必要。)

此外,您还有一个尚未提及的潜在错误:
浏览器
是一个
N分子
,但您正在调用
valueForKey:
,好像它是一个
NSDictionary
,而不是在
书签
上。这将导致unr的类似崩溃ecognized selector(即使对于dictionary对象,您也应该调用它;它主要用于/by,并执行您不需要的额外工作。我意识到这很混乱,因为我们是根据“键值对”来考虑的,但它确实存在…)

最后,您还可以稍微简化枚举代码。
NSDictionary
上的for-in循环枚举其键,就像
-keyEnumerator
一样

下面是我建议做最后一部分的方法:

NSURL *url
for (NSString *key in bookmarks) {
    url = [bookmarks objectForKey:key];
    NSLog(@"%@", [url absoluteURL]);
}

我正在学习相同的在线课程,发现上面的答案似乎都不起作用,要么是因为NSEnumerator可能不响应objectForKey,要么是因为不支持特定类型的枚举(与我不知道的OSX相比,iPhone SDK中可能不支持)。不过,我让它像一个魔咒一样工作,如下所示

NSString *aKey;
NSEnumerator *keyEnumerator = [bookmarks keyEnumerator];
NSURL *url;

while (aKey = [keyEnumerator nextObject])
{
    url = [bookmarks objectForKey:aKey];
    NSLog(@"value: %@", [url absoluteURL]);
}

这不是一个糟糕的答案,但代码中还有其他问题。有关详细信息,请参阅我的答案。此外,直接在dictionary对象上执行快速枚举速度更快。(奇怪的是,NSEnumerator对象每次调用只返回一个对象。这是一个很长的过程,而且与兼容性有关,因此您可以在快速枚举后使用相同的枚举器,而不会无意中跳过元素。)很好地理解了-valueForKey:的区别。事实是-valueForKey:是供Cocoa绑定使用的。文档说,除非键以“@”开头,否则它只调用-objectForKey:无论如何。通常最好直接调用该方法。
NSURL *url
for (NSString *key in bookmarks) {
    url = [bookmarks objectForKey:key];
    NSLog(@"%@", [url absoluteURL]);
}
NSString *aKey;
NSEnumerator *keyEnumerator = [bookmarks keyEnumerator];
NSURL *url;

while (aKey = [keyEnumerator nextObject])
{
    url = [bookmarks objectForKey:aKey];
    NSLog(@"value: %@", [url absoluteURL]);
}