【问题标题】:Opening a non-standard URL in a Cocoa app在 Cocoa 应用程序中打开非标准 URL
【发布时间】:2010-09-07 22:28:08
【问题描述】:

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

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 中是否有一些聪明的方法可以为我完成所有艰苦的工作?

【问题讨论】:

    标签: objective-c macos cocoa


    【解决方案1】:

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

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

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

    也许你希望它变成……

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

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

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


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

    【讨论】:

      【解决方案2】:

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

      stringByAddingPercentEscapesUsingEncoding:

      【讨论】:

        【解决方案3】:

        不幸的是,您需要比 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 字符串。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-04-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-20
          • 2010-12-13
          • 2019-05-30
          相关资源
          最近更新 更多