【发布时间】: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
我有一个这样的NSString:
http://www.
但我想将其转换为:
http%3A%2F%2Fwww.
我该怎么做?
【问题讨论】:
ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~ 这样的加密字符串 - 以下解决方案似乎都没有解决这个问题!
标签: ios objective-c swift nsstring urlencode
要转义你想要的字符需要更多的工作。
示例代码
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 \"%-.\^_`{|}~"
【讨论】:
-stringByAddingPercentEscapesUsingEncoding 方法。
stringByAddingPercentEscapesUsingEncoding 行为。它只编码 '&' 和 '=' 或类似荒谬的东西。
NSString 和characterSetWithCharactersInString 创建你需要的字符集,用invertedSet 取反,然后用stringByAddingPercentEncodingWithAllowedCharacters 使用它。有关示例,请参阅此SO answer。
它叫做URL encoding。更多here。
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
【讨论】:
CFURLCreateStringByAddingPercentEscapes() 已弃用。请改用[NSString stringByAddingPercentEncodingWithAllowedCharacters:]。
这不是我的解决方案。其他人在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 而不是 + 来表示空间。就是这样。
【讨论】:
NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );
NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];
【讨论】:
这可以在 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)
);}
【讨论】:
Swift iOS:
仅供参考:我用过这个:
extension String {
func urlEncode() -> CFString {
return CFURLCreateStringByAddingPercentEscapes(
nil,
self,
nil,
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
}
}// end extension String
【讨论】:
这是我使用的。请注意,您必须使用 @autoreleasepool 功能,否则程序可能会崩溃或锁定 IDE。在我意识到修复之前,我不得不重新启动我的 IDE 三次。看来此代码符合 ARC。
这个问题已经被问过很多次,也给出了很多答案,但遗憾的是所有被选中的问题(以及其他一些建议)都是错误的。
这是我使用的测试字符串:This is my 123+ test & 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;
}
}
【讨论】:
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)yourString,
NULL,
CFSTR("/:"),
kCFStringEncodingUTF8);
您需要自己释放或自动释放str。
【讨论】:
Google 在他们的Google Toolbox for Mac 中实现了这一点。所以这是一个很好的地方来展示他们如何做到这一点。另一种选择是包含工具箱并使用它们的实现。
检查实现here。 (这归结为人们在这里发布的内容)。
【讨论】:
这就是我快速执行此操作的方式。
extension String {
func encodeURIComponent() -> String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
}
func decodeURIComponent() -> String {
return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
}
}
【讨论】:
这就是我在 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
}
然后我在定义密码的地方调用了这个函数。
【讨论】:
//像这样使用NSString实例方法:
+ (NSString *)encodeURIComponent:(NSString *)string
{
NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
+ (NSString *)decodeURIComponent:(NSString *)string
{
NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
请记住,您应该只对您的参数值进行编码或解码,而不是您请求的所有 url。
【讨论】:
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 );
【讨论】: