Вопрос

Я новичок в 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:... forKey...] в коде.Проблема в вашем случае возникает потому, что вы пытаетесь рассматривать объекты NSURL как объекты NSString — [bookmarks objectForKey:(NSString *)each] — и словарь пытается получить длину предполагаемой строки, вызывая -length, который существует для NSString, но не для NSURL.

Если вы всегда создаете словарь с одними и теми же объектами, рассмотрите возможность использования более компактного конструктора varargs для NSDictionary.(Обратите внимание, что последний аргумент, разделенный запятыми, должен быть равен нулю — см. соответствующая документация) Вы также можете использовать -[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, но ты звонишь valueForKey: как если бы это был NSDictionary, а не на bookmarks.Это также приведет к аналогичному сбою и для нераспознанного селектора.(Даже для объектов словаря вам следует вызывать -objectForKey: вместо; -valueForKey: используется в основном для/кем Переплеты какао, и выполняет дополнительную работу, которая вам не нужна.Я понимаю, что это сбивает с толку, поскольку мы мыслим терминами «пары ключ-значение», но вот оно…)

Наконец, вы также можете несколько упростить код перечисления.(Цикл for-in на NSDictionary перечисляет свои ключи так же, как -keyEnumerator бы.)

Вот как я предлагаю сделать последнюю часть:

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

Другие советы

У вас отменена инициализация словаря закладок:

[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 напрямую, вместо того, чтобы сначала получать ключи (хотя вам вполне могут понадобиться ключи по какой-то другой причине).

Я думаю, что вы ссылаетесь на неправильную переменную в цикле while, пытаясь получить URL-адрес (и я думаю, вам следует использовать objectForKey: селектор для получения значения NSDictionary, а не valueForKey:):

NSEnumerator *browser = [bookmarks keyEnumerator];
id each;
NSURL *url;
while ((each = [browser nextObject])) {
    url = [bookmarks objectForKey:(NSString *)each]; // <-- bookmarks, not browser
    NSLog(@"URL = %@", url);
}

Я работаю над теми же онлайн-классами и обнаружил, что ни один из приведенных выше ответов, похоже, не работает либо потому, что NSEnumerator может не реагировать на objectForKey, либо потому, что конкретный тип перечисления не поддерживается (возможно, не в iPhone SDK по сравнению с OSX i). не знаю).Однако я заставил его работать как шарм следующим образом...

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

while (aKey = [keyEnumerator nextObject])
{
    url = [bookmarks objectForKey:aKey];
    NSLog(@"value: %@", [url absoluteURL]);
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top