2011-05-05 14 views
35

¿Cuál es una manera eficaz de tomar un objeto NSURL tales como los siguientes:iOS: analizar una dirección URL en segmentos

foo://name/12345 

y dividirla en una cadena y un entero sin signo, donde el val cadena es el nombre 'y el int sin firmar es 12345?

Supongo que el algoritmo implica la conversión de NSURL a un NSString y luego el uso de algunos componentes de NSScanner para terminar el resto.

Respuesta

19

NSURL tiene un método pathComponents, que devuelve una matriz con todos los diferentes componentes de ruta. Eso debería ayudarte a obtener la parte entera. Para obtener el nombre, usaría el método host del NSURL. Los documentos dicen que debería funcionar si la URL está formateada correctamente, así que pruébalo.

En general, no es necesario convertir en una cadena, parece que hay muchos métodos para calcular los componentes de la URL desde el objeto NSURL.

179

Solo puedo agregar un ejemplo aquí, la clase NSURL es la indicada. Esto no es completa, pero le dará una pista sobre cómo utilizar NSURL:

NSString *url_ = @"foo://name.com:8080/12345;param?foo=1&baa=2#fragment"; 
NSURL *url = [NSURL URLWithString:url_]; 

NSLog(@"scheme: %@", [url scheme]); 
NSLog(@"host: %@", [url host]); 
NSLog(@"port: %@", [url port]);  
NSLog(@"path: %@", [url path]);  
NSLog(@"path components: %@", [url pathComponents]);   
NSLog(@"parameterString: %@", [url parameterString]); 
NSLog(@"query: %@", [url query]);  
NSLog(@"fragment: %@", [url fragment]); 

de salida:

scheme: foo 
host: name.com 
port: 8080 
path: /12345 
path components: (
    "/", 
    12345 
) 
parameterString: param 
query: foo=1&baa=2 
fragment: fragment 

Este Q & Un NSURL's parameterString confusion with use of ';' vs '&' es también interesantes con respecto a las direcciones URL.

+0

Gracias por escribir todo esto a cabo – Sneakyness

+1

En mi experiencia, el uso de 'pathComponents' es arriesgado. De hecho, si los componentes de su ruta contienen un '/', incluso ENCODED, pathComponents lo decodificará y lo considerará como un separador. Prefiero analizar los componentes del camino yo mismo. –

+0

todo parece funcionar excepto [url parameterString] ... alguna idea de por qué podría ser "(nulo)" si el [url absoluteString] contiene exactamente lo que quiero? – whyoz

0

Gracias a Nick por orientarme en la dirección correcta.

Quería comparar las URL de archivos pero estaba teniendo problemas con las barras adicionales que hacen que isEqualString sea inútil. Puede usar mi ejemplo a continuación para comparar dos URLs primero deconstruirlas y luego comparar las partes entre sí.

- (BOOL) isURLMatch:(NSString*) url1 url2:(NSString*) url2 
{ 
    NSURL *u1 = [NSURL URLWithString:url1]; 
    NSURL *u2 = [NSURL URLWithString:url2]; 

    if (![[u1 scheme] isEqualToString:[u2 scheme]]) return NO; 
    if (![[u1 host] isEqualToString:[u2 host]]) return NO; 
    if (![[url1 pathComponents] isEqualToArray:[url2 pathComponents]]) return NO; 

    //check some properties if not nil as isEqualSting fails when comparing them 
    if ([u1 port] && [u2 port]) 
    { 
     if (![[u1 port] isEqualToNumber:[u2 port]]) return NO; 
    } 

    if ([u1 query] && [u2 query]) 
    { 
     if (![[u1 query] isEqualToString:[u2 query]]) return NO; 
    } 
    return YES; 
} 
8

En realidad, existe una mejor manera de analizar NSURL. Use NSURLComponents. Aquí está un ejemplo simle:

Swift:

extension URL { 
    var params: [String: String]? { 
     if let urlComponents = URLComponents(url: self, resolvingAgainstBaseURL: true) { 
      if let queryItems = urlComponents.queryItems { 
       var params = [String: String]() 
       queryItems.forEach{ 
        params[$0.name] = $0.value 
       } 
       return params 
      } 
     } 
     return nil 
    } 
} 

Objective-C:

NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; 
    NSArray *queryItems = [components queryItems]; 

    NSMutableDictionary *dict = [NSMutableDictionary new]; 

    for (NSURLQueryItem *item in queryItems) 
    { 
     [dict setObject:[item value] forKey:[item name]]; 
    } 
+0

Gracias, esto funcionó para mí :-) –

Cuestiones relacionadas