如何使用NSURLComponents将+编码到%2B中

Col*_*Col 15 encoding nsurl url-encoding swift

我正在使用NSURLComponents,我似乎无法获得正确编码的查询值.我需要最终的URL来表示+as %2B.

let baseUrl = NSURL(string: "http://www.example.com")    
let components = NSURLComponents(URL: baseUrl, resolvingAgainstBaseURL: true)
components.queryItems = [ NSURLQueryItem(name: "name", value: "abc+def") ]
XCTAssertEqual(components!.string!, "http://www.example.com?connectionToken=abc%2Bdef")
Run Code Online (Sandbox Code Playgroud)

失败!

输出等于:

http://www.example.com?connectionToken=abc+def 
Run Code Online (Sandbox Code Playgroud)

http://www.example.com?connectionToken=abc%2Bdef
Run Code Online (Sandbox Code Playgroud)

我已经尝试了几种变化,我似乎无法将其输出%2B.

Jim*_*her 22

我从Radar 24076063得到的答案解释了为什么它的工作方式(通过一些文本清理):

"+"字符在查询组件中是合法的,因此不需要进行百分比编码.

有些系统使用'+'作为空格,并且需要'+'加号字符进行百分比编码.但是,这种两阶段编码(将加号转换为%2B然后将空格转换为加号)容易出错,因为它很容易导致编码问题.如果URL被规范化,它也会中断(URL的语法规范化包括删除所有不必要的百分比编码 - 请参阅rfc3986第6.2.2.2节).

因此,如果由于您的代码正在与之交换的服务器而需要该行为,您将自己处理额外的转换.这是一段代码,显示了您需要做的两种方式:

NSURLComponents *components = [[NSURLComponents alloc] init];
NSArray *items = [NSArray arrayWithObjects:[NSURLQueryItem queryItemWithName:@"name" value:@"Value +"], nil];
components.queryItems = items;
NSLog(@"URL queryItems: %@", [components queryItems]);
NSLog(@"URL string before: %@", [components string]);

// Replace all "+" in the percentEncodedQuery with "%2B" (a percent-encoded +) and then replace all "%20" (a percent-encoded space) with "+"
components.percentEncodedQuery = [[components.percentEncodedQuery stringByReplacingOccurrencesOfString:@"+" withString:@"%2B"] stringByReplacingOccurrencesOfString:@"%20" withString:@"+"];
NSLog(@"URL string after: %@", [components string]);

// This is the reverse if you receive a URL with a query in that form and want to parse it with queryItems
components.percentEncodedQuery = [[components.percentEncodedQuery stringByReplacingOccurrencesOfString:@"+" withString:@"%20"] stringByReplacingOccurrencesOfString:@"%2B" withString:@"+"];
NSLog(@"URL string back: %@", [components string]);
NSLog(@"URL queryItems: %@", [components queryItems]);
Run Code Online (Sandbox Code Playgroud)

输出是:

URL queryItems: (
    "<NSURLQueryItem 0x100502460> {name = name, value = Value +}"
)

URL string before: ?name=Value%20+

URL string after: ?name=Value+%2B

URL string back: ?name=Value%20+

URL queryItems: (
    "<NSURLQueryItem 0x1002073e0> {name = name, value = Value +}"
)
Run Code Online (Sandbox Code Playgroud)

  • 道德:当添加没有固定规范的API时,您必须对模糊部分做出决策,这些决定对每个人都不起作用.使用NSURLComponents.queryItems,我们决定遵循rfc3986/std66(URI标准),了解哪些字符应该和不应该在名称和值字符串中进行百分比编码.在名称和值字符串中进行百分比编码的唯一有效查询组件字符是查询项分隔符'&'和'='.如果您想要替换其他字符或使用百分比编码,则此处的代码段显示了如何完成此操作. (2认同)

Vic*_*dan 9

正如其他答案所提到的,默认情况下,"+"不会在iOS上编码.但是,如果您的服务器要求进行编码,请按以下步骤操作:

var comps = URLComponents(url: self, resolvingAgainstBaseURL: true)
// a local var is needed to fix a swift warning about "overlapping accesses" caused by writing to the same property that's being read.
var compsCopy = comps
compsCopy?.queryItems = [URLQueryItem(name: "name", value: "abc+def")]
comps?.percentEncodedQuery = compsCopy?.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
Run Code Online (Sandbox Code Playgroud)


Ree*_*rse 0

这是苹果的一个错误。而是使用

NSString -stringByAddingPercentEncodingWithAllowedCharacters:
Run Code Online (Sandbox Code Playgroud)

NSCharacterSet +URLQueryAllowedCharacterSet
Run Code Online (Sandbox Code Playgroud)