在Cocoa应用程序中打开非标准URL

时间:2008-09-05 14:12:18

标签: objective-c macos cocoa

在我正在编写的应用程序中,我有一些像这样的代码:

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

NSURL* url = [NSURL URLWithString:myurl];

[ws openURL:url];

主要区别在于 myurl 来自我无法控制的地方。请注意URL中的%d不完全正确,表示URLWithString失败,返回 nil

处理此问题的“正确”方法是什么?我是否需要解析字符串并正确编码参数?或者Cocoa中是否有一些聪明的方法可以为我完成所有艰苦的工作?

3 个答案:

答案 0 :(得分:8)

我不确定这是否正是您正在寻找的,但NSString中有一个方法可以清理URL:

stringByAddingPercentEscapesUsingEncoding:

答案 1 :(得分:2)

我认为此处的行为是正确的,因为%d不是URL的有效组件(%是转义符,但需要两个十六进制字符跟随它)。

您不能只是对给定的URL进行URL编码,因为这会编码/ s和?s,这是您不想要的。

所以,问题是,这里的正确行为是什么?

也许你会希望它变成......

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

(即%会在URL中编码为%的编码版本,因此当方法获得输入时,它会将a视为设置为%d)

我认为没有任何库函数会为你做这样的事情,因为没有“正确”的方法来做到这一点。关于他只能纠正你能做的事情是返回一条错误信息,说你给出的URL无效(就像URLWithString一样)


如果你想尝试处理输入,我想你需要在URL中搜索任何%符号,这些符号后面没有两个十六进制字符,然后在这种情况下将%替换为%25。使用正则表达式应该是可能的,但我怀疑如果您的URL开始包含ASCII字符集之外的字符的编码版本,可能会有一些额外的复杂性。

答案 2 :(得分:1)

不幸的是,你需要比Apple提供的更聪明:

stringByAddingPercentEscapesUsingEncoding:

这将转义所有无效的URL字符,以便有效的“http://foo.com/hey%20dude/”变为“http://foo.com/hey%2520dud/”,这不是我们想要什么。

根据苹果文档:http://developer.apple.com/library/mac/documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html#//apple_ref/c/func/CFURLCreateStringByAddingPercentEscapes

我制作了一个NSURL类别,它做了正确的事情,并使用奇数字符串,如部分编码的字符串(即“http://foo.com/hey dude / i%20do%20it /").

以下是代码:

@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

它适用于UTF8字符串编码和ASCII编码。