代码之家  ›  专栏  ›  技术社区  ›  Stephen Darlington

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

  •  6
  • Stephen Darlington  · 技术社区  · 16 年前

    在我编写的应用程序中,我有如下代码:

    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失败,返回 .

    处理这个问题的“正确”方法是什么?是否需要分析字符串并正确编码参数?或者可可里有什么聪明的方法可以帮我做所有的努力吗?

    3 回复  |  直到 10 年前
        1
  •  8
  •   amrox    16 年前

    我不确定这是否正是您要查找的内容,但nsstring中有一个方法将清理URL:

    stringByAddingPercentEscapesUsingEncoding:

        2
  •  2
  •   Matt Sheppard    16 年前

    我认为这里的行为是正确的,因为%d不是一个有效的URL组件(即转义符,但后面需要两个十六进制字符)。

    你不能只使用url对给定的url进行编码,因为这样会对/s和进行编码?还有,这是你不想要的。

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

    也许你想把它变成…

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

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

    我不认为有任何库函数可以为您做这种事情,因为没有“正确”的方法可以做到这一点。关于他,你能做的唯一正确的事情就是返回一条错误消息,说明你得到的URL无效(就像urlWithString一样)


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

        3
  •  1
  •   nverinaud    12 年前

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

    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字符串一起工作。