为什么NSURL不接受包含引号或大括号的有效字符串?

时间:2016-04-23 04:44:32

标签: swift nsurl

修改

https://www.someurl.com/search?&access_token=1,84,848473938;848483,83&_json={"key1":"value1","key2":"value2"}

在声明具有JSON字符串的网址时,我显然需要使用大括号_json={ }和qoutes \"key1\":\"value1\"

然而,如果字符串中包含这些字符中的任何一个,那么

NSURL(string: String)会神奇地变为nil

正如在这里正确回答:NSURL is returning nil for a valid URL,我尝试使用:

let url = NSURL(string: url.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!)

但是我相信自从Swift 2发布之前就已经弃用了,我收到了错误:cannot convert value of Type NSCharacterSet to expected argument type NSStringEncoding (aka UInt)

所以我尝试使用

let url = NSURL(string: url.stringByAddingPercentEncodingWithAllowedCharacters(NSUTF8StringEncoding)!)!

虽然这确实允许NSURL有一个值而不是nil,但它没有返回预期的结果,所以有些东西仍然是错误的。

我知道格式是正确的,因为如果我在浏览器中手动输入URL字符串,我会得到预期的结果。如果我从Xcode复制/粘贴编码版本,它会像Swift一样在编码时给出错误的结果,如上所示。

非常感谢任何见解。

1 个答案:

答案 0 :(得分:1)

You can modify a mutable character set to remove an allowed character: since you want the commas to be encoded, remove the comma from the URLQueryAllowedCharacterSet before using it.

In Swift 2, we need to dance with NSMutableCharacterSet like this:

let sourceURL = "https://www.someurl.com/search?&access_token=1,84,848473938;848483,83&_json={\"key1\":\"value1\",\"key2\":\"value2\"}"

let charSet = NSMutableCharacterSet()
charSet.formUnionWithCharacterSet(NSCharacterSet.URLQueryAllowedCharacterSet())
charSet.removeCharactersInString(",")

let url = NSURL(string: sourceURL.stringByAddingPercentEncodingWithAllowedCharacters(charSet)!)

print(url!)

Prints:

https://www.someurl.com/search?&access_token=1%2C84%2C848473938;848483%2C83&_json=%7B%22key1%22:%22value1%22%2C%22key2%22:%22value2%22%7D

To do the same thing with Swift 3 we're using the CharacterSet struct instead of NSMutableCharacterSet but it's the same idea:

var charSet = CharacterSet()
charSet.formUnion(.urlQueryAllowed)
charSet.remove(",")
if let encoded = sourceURL.addingPercentEncoding(withAllowedCharacters: charSet) {
    if let url = URL(string: encoded) {
        print(url)
    }
}