Pregunta

Soy nuevo en Objective-C y no tengo ni idea de por qué este código no funciona:

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

El error que consigo es:

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'

Cualquier ayuda sería apreciada. Gracias.

¿Fue útil?

Solución

clave es lo que se utiliza para acceder a un objetivo en el diccionario. Que tenga sus llaves y objetos invertidos en cada línea se llama -[bookmarks setObject:... forKey...] en el código. El problema en el caso de que surja debido a que está tratando de tratar los objetos como objetos NSURL NSString - [bookmarks objectForKey:(NSString *)each] - y el diccionario está tratando de obtener la longitud de la supuesta cadena llamando -length, que existe para NSString pero no para NSURL .

Si siempre estás construyendo un diccionario con los mismos objetos, considere el uso de un más compacto "varargs" constructor de NSDictionary. (Tenga en cuenta que el último argumento separada por comas debe ser nulo - vea la documentación relacionada ) también puede utilizar -[NSDictionary dictionaryWithObjects:forKeys:] con dos objetos NSArray, que contiene las direcciones URL y los nombres de marcador. (Por cierto, fundición literales de cadena como NSString* para crear un NSURL es completamente innecesario.)

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

Además, tiene un error de acecho que no se ha mencionado todavía: browser es un NSEnumerator, pero usted está llamando a valueForKey: como si se tratara de un bookmarks, en lugar de en -objectForKey: . Eso va a causar un accidente similar para un selector no reconocido, también. (Incluso para objetos de diccionario, debe llamar -valueForKey: lugar; -keyEnumerator se utiliza sobre todo para / por Cocoa enlaces , y hace un trabajo extra que no es necesario me doy cuenta que es confuso ya que pensamos en. términos de "pares de clave y valor", pero no lo es ...)

Por último, también se puede simplificar el código de enumeración un tanto. (Un bucle for-in en una <=> enumera sus llaves al igual que lo haría <=>.)

Así es como yo sugeriría hacer la última parte:

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

Otros consejos

Tiene el diccionario marcadores intiialization invierte:

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

En caso de ser:

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

Además, hay una manera más sencilla de hacer la enumeración:

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

También puede enumerar [marcadores allValues] para obtener el objeto URL directamente en vez de conseguir las llaves primera (aunque usted puede querer las teclas por alguna otra razón).

Creo que te refieres a la variable mal en su bucle while cuando se trata de obtener la dirección URL (y creo que usted debe utilizar el selector de objectForKey: para obtener un valor de un NSDictionary, no valueForKey:):

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

Estoy trabajando a través de las mismas clases en línea y encontró que ninguna de las respuestas anteriores parece funcionar bien porque NSEnumerator puede no responder a objectForKey o porque el tipo particular de enumeración no es compatible (tal vez no en el iPhone SDK, en comparación a OSX no sé). Tengo que trabajar como un encanto de la siguiente manera, aunque ...

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

while (aKey = [keyEnumerator nextObject])
{
    url = [bookmarks objectForKey:aKey];
    NSLog(@"value: %@", [url absoluteURL]);
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top