2008-09-05 4 views
6

Dans une application que je vous écris, j'ai un code comme ceci:Ouverture d'une URL non standard dans une application Cocoa

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

NSURL* url = [NSURL URLWithString:myurl]; 

[ws openURL:url]; 

La principale différence étant que myurl vient de quelque part en dehors de mon contrôle. Notez le% d dans l'URL qui n'est pas entièrement correct et signifie que URLWithString échoue, renvoyant nul.

Quelle est la "bonne" façon de gérer cela? Ai-je besoin d'analyser la chaîne et d'encoder correctement les arguments? Ou y at-il une méthode intelligente dans Cocoa qui fait tout le travail dur pour moi?

Répondre

2

Je pense que le comportement ici est correct, car% d n'est pas un composant valide d'une URL (% est l'échappement, mais attend deux caractères hexadécimaux pour le suivre).

Vous ne pouvez pas simplement encoder l'URL comme vous l'avez reçu, car cela encoderait les/s et? S, ce que vous ne voulez pas. Donc, la question est: quel est le comportement correct ici?

Peut-être que vous voulez qu'il soit transformé en ...

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

(à savoir le% est encode à la version codée% dans une URL, donc lorsque la méthode obtient l'entrée, il voit un comme étant défini sur% d)

Je ne pense pas qu'il existe une fonction de bibliothèque qui fera ce genre de chose pour vous, car il n'y a pas de manière «correcte» de le faire. A propos, il ne bonne chose que vous pouvez faire est retourner un message d'erreur indiquant l'URL que vous avez reçu est invalide (comme URLWithString est)


Si vous voulez essayer de gérer l'entrée, je suppose que vous devez recherchez dans l'URL les symboles% qui ne sont pas immédiatement suivis de deux caractères hexadécimaux, puis remplacez le% par% 25 dans ce cas. Cela devrait être tout à fait possible avec une expression régulière, bien que je soupçonne qu'il peut y avoir des complexités supplémentaires si vos URL commencent à contenir des versions codées de caractères en dehors du jeu de caractères ASCII.

1

Malheureusement, vous devez être plus intelligent que ce est fourni par Apple:

stringByAddingPercentEscapesUsingEncoding: 

Cela tous les caractères d'URL non valides pour que « http://foo.com/hey%20dude/ », qui est valide, devient « http://foo.com/ hey% 2520dud/", ce qui n'est pas ce que nous voulons.

Selon la documentation de pomme: http://developer.apple.com/library/mac/documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html#//apple_ref/c/func/CFURLCreateStringByAddingPercentEscapes

je fait une catégorie NSURL qui fait la bonne chose et fonctionne avec une corde étrange tels que ceux avec le codage partiel (par exemple « http://foo.com/hey mec/i % 20do% 20it/").

Voici le code:

@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 

Il fonctionne très bien avec la chaîne UTF8 les encodées et ASCII.

Questions connexes