【问题标题】:Objective-C and Swift URL encodingObjective-C 和 Swift URL 编码
【发布时间】:2011-12-26 13:26:26
【问题描述】:

我有一个这样的NSString

http://www.

但我想将其转换为:

http%3A%2F%2Fwww.

我该怎么做?

【问题讨论】:

  • 我有一个像ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~ 这样的加密字符串 - 以下解决方案似乎都没有解决这个问题!

标签: ios objective-c swift nsstring urlencode


【解决方案1】:

要转义你想要的字符需要更多的工作。

示例代码

iOS7 及以上:

NSString *unescaped = @"http://www";
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(@"escapedString: %@", escapedString);

NSLog 输出:

转义字符串:http%3A%2F%2Fwww

以下是有用的 URL 编码字符集:

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

创建一个结合以上所有内容的字符集:

NSCharacterSet *URLCombinedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>?@[\\]^`{|}"] invertedSet];

创建一个 Base64

Base64字符集的情况下:

NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet];

对于 Swift 3.0:

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)

对于 Swift 2.x:

var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())

注意:stringByAddingPercentEncodingWithAllowedCharacters 也会对需要编码的 UTF-8 字符进行编码。

iOS7 前使用 Core Foundation
将 Core Foundation 与 ARC 一起使用:

NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
    NULL,
   (__bridge CFStringRef) unescaped,
    NULL,
    CFSTR("!*'();:@&=+$,/?%#[]\" "),
    kCFStringEncodingUTF8));

在没有 ARC 的情况下使用 Core Foundation:

NSString *escapedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
    NULL,
   (CFStringRef)unescaped,
    NULL,
    CFSTR("!*'();:@&=+$,/?%#[]\" "),
    kCFStringEncodingUTF8);

注意:-stringByAddingPercentEscapesUsingEncoding 不会产生正确的编码,在这种情况下,它不会对返回相同字符串的任何内容进行编码。

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding 编码 14 个字符:

`#%^{}[]|\" 加上空格字符作为百分比转义。

测试字符串:

" `~!@#$%^&*()_+-={}[]|\\:;\"'<,>.?/AZaz"  

编码字符串:

"%20%60~!@%23$%25%5E&*()_+-=%7B%7D%5B%5D%7C%5C:;%22'%3C,%3E.?/AZaz"  

注意:请考虑这组字符是否满足您的需求,如果不能根据需要进行更改。

RFC 3986 需要编码的字符(% 添加,因为它是编码前缀字符):

"!#$&'()*+,/:;=?@[]%"

一些“未保留字符”被额外编码:

"\n\r \"%-.\^_`{|}~"

【讨论】:

  • 另外注意你可以使用 NSString 的-stringByAddingPercentEscapesUsingEncoding 方法。
  • 啊,是的,现在我想起了时髦的 stringByAddingPercentEscapesUsingEncoding 行为。它只编码 '&' 和 '=' 或类似荒谬的东西。
  • 根据RFC1738,您还需要对其他字符进行编码。因此,尽管这确实回答了 OP 的问题,但它作为通用 URL 编码器的用处有限。例如,它不处理非字母数字,例如德语变音符号。
  • 这不起作用(对于 iOS 7 部分)。这不会将 & 转换为 %26。
  • NSStringcharacterSetWithCharactersInString 创建你需要的字符集,用invertedSet 取反,然后用stringByAddingPercentEncodingWithAllowedCharacters 使用它。有关示例,请参阅此SO answer
【解决方案2】:

它叫做URL encoding。更多here

-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
           (CFStringRef)self,
           NULL,
           (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
           CFStringConvertNSStringEncodingToEncoding(encoding));
}

【讨论】:

  • 如果您发布的链接中的某些内容包含在答案中,这将更加有用。
  • CFURLCreateStringByAddingPercentEscapes() 已弃用。请改用[NSString stringByAddingPercentEncodingWithAllowedCharacters:]
【解决方案3】:

这不是我的解决方案。其他人在stackoverflow中写过,但我忘记了。

不知何故,这个解决方案“很好”。它可以处理变音符号、汉字以及几乎所有其他内容。

- (NSString *) URLEncodedString {
    NSMutableString * output = [NSMutableString string];
    const char * source = [self UTF8String];
    int sourceLen = strlen(source);
    for (int i = 0; i < sourceLen; ++i) {
        const unsigned char thisChar = (const unsigned char)source[i];
        if (false && thisChar == ' '){
            [output appendString:@"+"];
        } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
                   (thisChar >= 'a' && thisChar <= 'z') ||
                   (thisChar >= 'A' && thisChar <= 'Z') ||
                   (thisChar >= '0' && thisChar <= '9')) {
            [output appendFormat:@"%c", thisChar];
        } else {
            [output appendFormat:@"%%%02X", thisChar];
        }
    }
    return output;
}

如果有人能告诉我这段代码是谁编写的,我将不胜感激。基本上他有一些解释为什么这个编码的字符串会完全按照它的意愿解码。

我稍微修改了他的解决方案。我喜欢用 %20 而不是 + 来表示空间。就是这样。

【讨论】:

  • 什么是 [self UTF8String] ?
  • @yuchaozh 这是一个放在 NSString 类别中的函数。因此,self 是 NSStirng,并且 [self UTF8String] 假设返回其 UTF8 格式的字符串。
【解决方案4】:
 NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );

NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];

【讨论】:

  • 发布encodedString 和url。这段代码是关于编码参数的。编码整个地址传递字符串而不是“参数”。
  • 这对我有用...甚至编码了我遇到问题的 & 字符。
【解决方案5】:

这可以在 Objective C ARC 中工作。使用 CFBridgingRelease 将 Core Foundation 样式的对象转换为 Objective-C 对象并将对象的所有权转移给 ARC。请参阅Function CFBridgingRelease 此处。

+ (NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes
                         (kCFAllocatorDefault,
                          (__bridge CFStringRef)string,
                          NULL,
                          CFSTR("!*'();:@&=+$,/?%#[]"),
                          kCFStringEncodingUTF8)
                         );}

【讨论】:

    【解决方案6】:

    Swift iOS:

    仅供参考:我用过这个:

    extension String {
    
        func urlEncode() -> CFString {
            return CFURLCreateStringByAddingPercentEscapes(
                nil,
                self,
                nil,
                "!*'();:@&=+$,/?%#[]",
                CFStringBuiltInEncodings.UTF8.rawValue
            )
        }
    
    }// end extension String
    

    【讨论】:

      【解决方案7】:

      这是我使用的。请注意,您必须使用 @autoreleasepool 功能,否则程序可能会崩溃或锁定 IDE。在我意识到修复之前,我不得不重新启动我的 IDE 三次。看来此代码符合 ARC。

      这个问题已经被问过很多次,也给出了很多答案,但遗憾的是所有被选中的问题(以及其他一些建议)都是错误的。

      这是我使用的测试字符串:This is my 123+ test &amp; test2. Got it?!

      这些是我的 Objective C++ 类方法:

      static NSString * urlDecode(NSString *stringToDecode) {
          NSString *result = [stringToDecode stringByReplacingOccurrencesOfString:@"+" withString:@" "];
          result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
          return result;
      }
      
      static NSString * urlEncode(NSString *stringToEncode) {
          @autoreleasepool {
              NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                      NULL,
                      (CFStringRef)stringToEncode,
                      NULL,
                      (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
                      kCFStringEncodingUTF8
                  ));
              result = [result stringByReplacingOccurrencesOfString:@"%20" withString:@"+"];
              return result;
          }
      }
      

      【讨论】:

        【解决方案8】:
        NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                                     NULL,
                                     (CFStringRef)yourString, 
                                     NULL, 
                                     CFSTR("/:"), 
                                     kCFStringEncodingUTF8);
        

        您需要自己释放或自动释放str

        【讨论】:

          【解决方案9】:

          Google 在他们的Google Toolbox for Mac 中实现了这一点。所以这是一个很好的地方来展示他们如何做到这一点。另一种选择是包含工具箱并使用它们的实现。

          检查实现here。 (这归结为人们在这里发布的内容)。

          【讨论】:

            【解决方案10】:

            这就是我快速执行此操作的方式。

            extension String {
                func encodeURIComponent() -> String {
                    return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
                }
            
                func decodeURIComponent() -> String {
                    return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
                }
            }
            

            【讨论】:

              【解决方案11】:

              这就是我在 Swift 5 上所做的:

              func formatPassword() -> String {
                  
                  var output = "";
              
                  for ch in self {
              
                      let char = String(ch)
              
                      switch ch {
              
                          case " ":
                              output.append("+")
              
                              break
              
                          case ".", "-", "_", "~", "a"..."z", "A"..."Z", "0"..."9":
              
                              output.append(char)
              
                              break
              
                              default:
              
                              print(ch)
              
                              let unicode = char.unicodeScalars.first?.value ?? 0
              
                              let unicodeValue = NSNumber(value: unicode).intValue
              
                              let hexValue = String(format: "%02X", arguments: [unicodeValue])
              
                              output = output.appendingFormat("%%%@", hexValue)
              
                              }
              
                          }
                  
                  return output as String
              }
              

              然后我在定义密码的地方调用了这个函数。

              【讨论】:

                【解决方案12】:

                //像这样使用NSString实例方法:

                + (NSString *)encodeURIComponent:(NSString *)string
                {
                NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
                return s;
                }
                
                + (NSString *)decodeURIComponent:(NSString *)string
                {
                NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
                return s;
                }
                

                请记住,您应该只对您的参数值进行编码或解码,而不是您请求的所有 url。

                【讨论】:

                • stringByReplacingPercentEscapeusingencoding: 只转义 & 和 = :-(
                • 正确,所以像 + 这样的东西在需要的时候不会被编码。所以不要使用上面的答案
                【解决方案13】:
                int strLength = 0;
                NSString *urlStr = @"http://www";
                NSLog(@" urlStr : %@", urlStr );
                NSMutableString *mutableUrlStr = [urlStr mutableCopy];
                NSLog(@" mutableUrlStr : %@", mutableUrlStr );
                strLength = [mutableUrlStr length];
                [mutableUrlStr replaceOccurrencesOfString:@":" withString:@"%3A" options:NSCaseInsensitiveSearch range:NSMakeRange(0, strLength)];
                NSLog(@" mutableUrlStr : %@", mutableUrlStr );
                strLength = [mutableUrlStr length];
                [mutableUrlStr replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSCaseInsensitiveSearch range:NSMakeRange(0, strLength)];
                NSLog(@" mutableUrlStr : %@", mutableUrlStr );
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2018-06-11
                  • 2014-02-19
                  • 1970-01-01
                  • 2014-07-30
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多