我有一个像这样的
NSString
:
http://www.
但我想把它改成这样:
http%3A%2F%2Fwww.
我该怎么做?
要转义你想要的字符需要更多的工作。
示例代码
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 个字符(添加%,因为它是编码前缀字符):
"!#$&'()*+,/:;=?@[]%"
一些“非保留字符”被额外编码:
” \"%-.<>\^_`{|}~"
这不是我的解决方案。其他人在 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。请参阅此处 CFBridgingRelease 函数。
+ (NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes
(kCFAllocatorDefault,
(__bridge CFStringRef)string,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
kCFStringEncodingUTF8)
);}
这是我用的。请注意,您必须使用
@autoreleasepool
功能,否则程序可能会崩溃或锁定 IDE。我必须重新启动 IDE 3 次才能解决问题。看来此代码符合 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;
}
}
Swift iOS:
仅供参考:我用过这个:
extension String {
func urlEncode() -> CFString {
return CFURLCreateStringByAddingPercentEscapes(
nil,
self,
nil,
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
}
}// end extension String
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)yourString,
NULL,
CFSTR("/:"),
kCFStringEncodingUTF8);
您需要自己释放或自动释放
str
。
Google 在其 Google Toolbox for Mac 中实现了这一点。所以这是一个展示他们如何做的好地方。另一种选择是包含工具箱并使用它们的实现。
extension String {
func encodeURIComponent() -> String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
}
func decodeURIComponent() -> String {
return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
}
}
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 *)encodeURIComponent:(NSString *)string
{
NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
+ (NSString *)decodeURIComponent:(NSString *)string
{
NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
记住,您应该只对您的参数值进行编码或解码,而不是您请求的所有网址。
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 );