Objective-C NSDictionary和NSURL的问题

时间:2009-06-29 18:28:41

标签: debugging nsstring nsdictionary nsurl

我是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'

任何帮助将不胜感激。 感谢。

4 个答案:

答案 0 :(得分:10)

是您用来访问词典中对象的方法。在代码中调用-[bookmarks setObject:... forKey...]的每一行上都可以反转键和对象。您的案例中出现的问题是因为您尝试将NSURL对象视为NSString对象 - [bookmarks objectForKey:(NSString *)each] - 并且字典试图通过调用-length来获取所谓的字符串的长度,该{1}}存在于NSString中但不适用于NSURL。

如果您总是使用相同的对象构建字典,请考虑为NSDictionary使用更紧凑的“varargs”构造函数。 (请注意,最后一个以逗号分隔的参数必须为nil - 请参阅the related documentation)您还可以将-[NSDictionary dictionaryWithObjects:forKeys:]与两个NSArray对象一起使用,其中包含URL和书签名称。 (顺便说一下,将字符串文字强制为NSString*来创建NSURL是完全没必要的。)

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];

此外,您还有一个尚未提及的潜在错误: browser NSEnumerator,但您正在呼叫 {{1 }} 好像是valueForKey:,而不是 NSDictionary 。这也会导致无法识别的选择器发生类似的崩溃。 (即使对于字典对象,也应该调用-objectForKey:; -valueForKey:主要用于/ Cocoa Bindings,并且做额外的工作你不需要。我发现自从我们认为这令人困惑就“键值对”而言,它是......)

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

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

-keyEnumerator

答案 1 :(得分:3)

你的书签词典推理反转:

[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对象,而不是首先获取密钥(尽管您可能因其他原因需要密钥)。

答案 2 :(得分:1)

我认为你在尝试获取URL时指的是你的while循环中的错误变量(我认为你应该使用objectForKey:选择器来获取NSDictionary的值,而不是{{1 }}):

valueForKey:

答案 3 :(得分:1)

我正在使用相同的在线课程,发现上述答案似乎都没有用,因为NSEnumerator可能无法响应objectForKey,或者因为不支持特定类型的枚举(可能不会在iPhone SDK中进行比较)到OSX我不知道)。我让它像魅力一样工作如下......

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

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