2008-09-05 13 views
6

En una aplicación que estoy escribiendo tengo algo de código como este:Abrir una URL no estándar en una aplicación Cocoa

NSWorkspace* ws = [NSWorkspace sharedWorkspace]; 
NSString* myurl = @"http://www.somewebsite.com/method?a=%d"; 

NSURL* url = [NSURL URLWithString:myurl]; 

[ws openURL:url]; 

La diferencia principal es que myurl proviene de algún lugar fuera de mi control. Tenga en cuenta el% d en la URL que no es del todo correcto y significa que URLWithString falla, devolviendo nil.

¿Cuál es la forma "correcta" de manejar esto? ¿Debo analizar la cadena y codificar correctamente los argumentos? ¿O hay algún método inteligente en Cocoa que hace todo el trabajo duro para mí?

Respuesta

2

Creo que el comportamiento aquí es correcto, porque% d no es un componente válido de una URL (% es el escape, pero espera que dos caracteres hexadecimales lo sigan).

No puede codificar URL solo como se le ha dado, porque eso codificaría el/sy también, que usted no quiere.

Entonces, la pregunta es, ¿cuál es el comportamiento correcto aquí?

Tal vez usted quiere que se convierta en ...

http://www.somewebsite.com/method?a=%25d 

(es decir, el% se codifican a la versión codificada de% en una dirección URL, por lo que cuando se pone el método de entrada, se ve una como se establece en% d)

No creo que haya ninguna función de biblioteca que haga ese tipo de cosas, ya que no hay una forma "correcta" de hacerlo. Sobre él lo único correcto que puede hacer es devolver un mensaje de error que indica la dirección URL que se les dio no es válido (al igual que URLWithString es)


Si quisiera tratar de manejar la entrada, supongo que tendría que busque en la URL los símbolos% que no estén seguidos inmediatamente por dos caracteres hexadecimales, y luego reemplace el% con% 25 en ese caso. Eso debería ser posible con una expresión regular, aunque sospecho que puede haber algunas complejidades adicionales si las URL comienzan a contener versiones codificadas de caracteres fuera del conjunto de caracteres ASCII.

1

Desafortunadamente Tienes que ser más inteligente que lo se proporciona por Apple:

stringByAddingPercentEscapesUsingEncoding: 

Esto escapar todos los caracteres no válidos URL para que "http://foo.com/hey%20dude/", que es válido, se convierte en "http://foo.com/ hey% 2520dud/", que no es lo que queremos.

De acuerdo con la documentación de manzana: http://developer.apple.com/library/mac/documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html#//apple_ref/c/func/CFURLCreateStringByAddingPercentEscapes

Hice una categoría NSURL el que hace lo correcto y funciona con una cuerda extraño -como los que incluyen la codificación parcial (es decir, "http://foo.com/hey tio/i % 20do% 20it/").

Aquí está el código:

@interface NSURL (SmartEncoding) 
+ (NSURL *)smartURLWithString:(NSString *)str; 
@end 

@implementation NSURL (SmartEncoding) 

+ (NSURL *)smartURLWithString:(NSString *)str 
{ 
    CFStringRef preprocessed = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)str, CFSTR(""), kCFStringEncodingUTF8); 
    if (!preprocessed) 
     preprocessed = CFURLCreateStringByReplacingPercentEscapesUsingEncoding(NULL, (CFStringRef)str, CFSTR(""), kCFStringEncodingASCII); 

    if (!preprocessed) 
     return [NSURL URLWithString:str]; 

    CFStringRef sanitized = CFURLCreateStringByAddingPercentEscapes(NULL, preprocessed, NULL, NULL, kCFStringEncodingUTF8); 
    CFRelease(preprocessed); 
    NSURL *result = (NSURL*)CFURLCreateWithString(NULL, sanitized, NULL); 
    CFRelease(sanitized); 
    return [result autorelease]; 
} 

@end 

Funciona bien con la cadena UTF8 los codificados y ASCII.

Cuestiones relacionadas