Los problemas de Objective-C con NSDictionary y NSURL
-
21-08-2019 - |
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.
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]);
}