如何在Swift 2.0中使用stringByAddingPercentEncodingWithAllowedCharacters()方法来处理URL?

69

我在 Swift 1.2 中使用了这个。

let urlwithPercentEscapes = myurlstring.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

现在这给出了一个警告,要求我使用

stringByAddingPercentEncodingWithAllowedCharacters

我需要将一个NSCharacterSet用作参数,但是有这么多选择,我无法确定哪个会给我与之前使用的方法相同的结果。

我想要使用的示例URL将像这样

http://www.mapquestapi.com/geocoding/v1/batch?key=YOUR_KEY_HERE&callback=renderBatch&location=Pottsville,PA&location=Red Lion&location=19036&location=1090 N Charlotte St, Lancaster, PA
URL 字符集用于编码,似乎包含可以修剪我的URL的集合。例如,在链接 http://www.example.com/index.php?key1=value1 中,路径组件为 /index.php。但是我不想修剪它的任何方面。当我使用字符串myurlstring时,会失败。但是使用以下字符串就没有问题了,它会用一些魔法进行编码,然后我就可以获得我的URL数据。
let urlwithPercentEscapes = myurlstring.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
它使用给定的编码返回字符串的表示形式,以确定百分号转义所需的内容,以将字符串转换为合法的URL字符串。
谢谢。
6个回答

161

对于给定的URL字符串,其相当于

let urlwithPercentEscapes = myurlstring.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

字符集是URLQueryAllowedCharacterSet吗?

let urlwithPercentEscapes = myurlstring.stringByAddingPercentEncodingWithAllowedCharacters( NSCharacterSet.URLQueryAllowedCharacterSet())

Swift 3:

let urlwithPercentEscapes = myurlstring.addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)

URL字符串中问号后面的所有内容都被编码。

由于方法stringByAddingPercentEncodingWithAllowedCharacters可能返回nil,请像Leo Dabus的答案中建议的那样使用可选绑定。


有道理,谢谢 - 如果你有时间,能帮忙解决这个问题吗?http://stackoverflow.com/questions/32061298/could-geocodeaddressdictionary-in-ios-9-be-implemented-different-from-ios-8 - DogCoffee

21

这将取决于你的URL。如果你的URL是一个路径,你可以使用字符集urlPathAllowed

let myFileString = "My File.txt"
if let urlwithPercentEscapes = myFileString.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) {
    print(urlwithPercentEscapes)  // "My%20File.txt"
}

创建用于 URL 编码的字符集

urlFragmentAllowed:允许使用在 URL 片段中的字符集

urlHostAllowed:允许使用在 URL 主机名中的字符集

urlPasswordAllowed:允许使用在 URL 密码中的字符集

urlQueryAllowed:允许使用在 URL 查询中的字符集

urlUserAllowed:允许使用在 URL 用户名中的字符集

你也可以创建自己的 URL 字符集:

let myUrlString = "http://www.mapquestapi.com/geocoding/v1/batch?key=YOUR_KEY_HERE&callback=renderBatch&location=Pottsville,PA&location=Red Lion&location=19036&location=1090 N Charlotte St, Lancaster, PA"

let urlSet = CharacterSet.urlFragmentAllowed
                .union(.urlHostAllowed)
                .union(.urlPasswordAllowed)
                .union(.urlQueryAllowed)
                .union(.urlUserAllowed)

extension CharacterSet {
    static let urlAllowed = CharacterSet.urlFragmentAllowed
                                        .union(.urlHostAllowed)
                                        .union(.urlPasswordAllowed)
                                        .union(.urlQueryAllowed)
                                        .union(.urlUserAllowed)
}

if let urlwithPercentEscapes = myUrlString.addingPercentEncoding(withAllowedCharacters: .urlAllowed) {
    print(urlwithPercentEscapes)  // "http://www.mapquestapi.com/geocoding/v1/batch?key=YOUR_KEY_HERE&callback=renderBatch&location=Pottsville,PA&location=Red%20Lion&location=19036&location=1090%20N%20Charlotte%20St,%20Lancaster,%20PA"
}

另一种选择是使用URLComponents来正确创建您的URL


请提供更多信息以便我能够翻译相关的编程内容。 - DogCoffee
3
更重要的是,您需要将适当的字符集应用于URL的每个部分。由于不同的部分具有不同的功能,因此没有单一的解决方案。 - Wain
@Wain非常正确,这也是警告所说的。在此答案中仅使用具有WhiteSpace的部分似乎有效。 - DogCoffee
@DogCoffee 你可以创建一个自定义集合。 - Leo Dabus
@LeoDabus 不知道从哪里开始。但如果情况恶化,会考虑这个问题。另外,Map Quest 返回一些奇怪的语法,围绕着他们的 JSON。 - DogCoffee

7

Swift 3.0 (From grokswift)

使用字符串创建URL容易出现错误。只需漏掉一个 / 或者误用 ? 进行查询编码,就会导致API调用失败,您的应用程序将无法显示任何数据(甚至崩溃,如果您没有预料到这种可能性)。自iOS 8以来,使用 NSURLComponentsNSURLQueryItems 创建URL更加简单。

func createURLWithComponents() -> URL? {
        var urlComponents = URLComponents()
        urlComponents.scheme = "http"
        urlComponents.host = "www.mapquestapi.com"
        urlComponents.path = "/geocoding/v1/batch"

        let key = URLQueryItem(name: "key", value: "YOUR_KEY_HERE")
        let callback = URLQueryItem(name: "callback", value: "renderBatch")
        let locationA = URLQueryItem(name: "location", value: "Pottsville,PA")
        let locationB = URLQueryItem(name: "location", value: "Red Lion")
        let locationC = URLQueryItem(name: "location", value: "19036")
        let locationD = URLQueryItem(name: "location", value: "1090 N Charlotte St, Lancaster, PA")

        urlComponents.queryItems = [key, callback, locationA, locationB, locationC, locationD]

        return urlComponents.url
}

以下是使用 guard 语句访问 URL 的代码。
guard let url = createURLWithComponents() else {
            print("invalid URL")
            return nil
      }
      print(url)

输出:

http://www.mapquestapi.com/geocoding/v1/batch?key=YOUR_KEY_HERE&callback=renderBatch&location=Pottsville,PA&location=Red%20Lion&location=19036&location=1090%20N%20Charlotte%20St,%20Lancaster,%20PA

3
在Swift 3.1中,我正在使用以下类似的内容:
let query = "param1=value1&param2=" + valueToEncode.addingPercentEncoding(withAllowedCharacters: .alphanumeric)

它比.urlQueryAllowed和其他编码更安全,因为它将编码除A-Z、a-z和0-9之外的每个字符。当您要编码的值可能包含像?、&、=、+和空格这样的特殊字符时,这种方法更加有效。


2

在我的情况下,最后一个组件是非拉丁字符时,我在Swift 2.2中执行以下操作:

extension String {
 func encodeUTF8() -> String? {
//If I can create an NSURL out of the string nothing is wrong with it
if let _ = NSURL(string: self) {

    return self
}

//Get the last component from the string this will return subSequence
let optionalLastComponent = self.characters.split { $0 == "/" }.last


if let lastComponent = optionalLastComponent {

    //Get the string from the sub sequence by mapping the characters to [String] then reduce the array to String
    let lastComponentAsString = lastComponent.map { String($0) }.reduce("", combine: +)


    //Get the range of the last component
    if let rangeOfLastComponent = self.rangeOfString(lastComponentAsString) {
        //Get the string without its last component
        let stringWithoutLastComponent = self.substringToIndex(rangeOfLastComponent.startIndex)


        //Encode the last component
        if let lastComponentEncoded = lastComponentAsString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()) {


        //Finally append the original string (without its last component) to the encoded part (encoded last component)
        let encodedString = stringWithoutLastComponent + lastComponentEncoded

            //Return the string (original string/encoded string)
            return encodedString
        }
    }
}

return nil;
}
}

0

Swift 4.0

let encodedData = myUrlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接