Objective-C 和 Swift URL 编码

我的 NSString是这样的:

http://www.

但我想把它变成:

http%3A%2F%2Fwww.

我怎么能这么做?

118446 次浏览

这叫做 URL 编码更多的 给你

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

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

要摆脱你想要的角色是一个多一点的工作。

示例代码

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字符。

Pre iOS7使用核心基础
使用 ARC 的核心基础:

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

使用没有 ARC 的核心基础:

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

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

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding编码14个字符:

“ #% ^ {}[] |”< > 加上空格字符作为转义百分比。

TestString:

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

EncodedString:

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

注意: 考虑一下这组字符是否满足您的需要,如果没有根据需要更改它们。

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

“ ! # $& () * + ,/: = ?@[]%”

一些“无保留字符”是另外编码的:

“ n r”%-. < > ^ _‘{ | } ~”

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 );
 NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );


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

这不是我的解决方案。有人写了堆栈溢出,但我已经忘了如何。

不知何故,这个解决方案“很好”。它处理发音符号,中文字符,以及几乎任何其他东西。

- (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 实例方法:

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


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

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

斯威夫特 iOS:

仅供参考: 我用过这个:

extension String {


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


}// end extension String

谷歌在他们的 面向 Mac 的谷歌工具箱中实现了这一点。所以这是一个很好的地方,他们是如何做到这一点。另一种选择是包含“工具箱”并使用它们的实现。

检查实现 给你。(这可以精确地归结为人们在这里发布了什么)。

我就是这么迅速做到的。

extension String {
func encodeURIComponent() -> String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
}


func decodeURIComponent() -> String {
return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
}
}

这是我用的。注意,必须使用 @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;
}
}

这可以在 Objective C ARC 中工作。使用 CFBridgingrelease 将 Core Foundation 风格的对象转换为 Objective-C 对象,并将对象的所有权转移给 ARC。请参阅这里的 功能 CFBridge 释放

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

这就是我在 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
}

然后调用定义密码的函数。