如何在Swift中编码一个URL

这是我的URL

问题是, address字段没有被追加到urlpath

有谁知道这是为什么?

 var address:string address = "American Tourister, Abids Road, Bogulkunta, Hyderabad, Andhra Pradesh, India" let urlpath = NSString(format: "http://maps.googleapis.com/maps/api/geocode/json?address="+"\(address)") 

使用stringByAddingPercentEncodingWithAllowedCharacters

 var escapedAddress = address.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) 

使用stringByAddingPercentEscapesUsingEncoding: 在iOS 9和OS X v10.11中弃用

 var address = "American Tourister, Abids Road, Bogulkunta, Hyderabad, Andhra Pradesh, India" var escapedAddress = address.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) let urlpath = NSString(format: "http://maps.googleapis.com/maps/api/geocode/json?address=\(escapedAddress)") 

SWIFT 3

 var address = "American Tourister, Abids Road, Bogulkunta, Hyderabad, Andhra Pradesh, India" let escapedAddress = address.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) let urlpath = String(format: "http://maps.googleapis.com/maps/api/geocode/json?address=\(escapedAddress)") 

Swift 3:

 let escapedString = originalString.addingPercentEncoding(withAllowedCharacters:NSCharacterSet.urlQueryAllowed) 

如果您添加到您的URL的值可能具有保留字符(如RFC 3986的第2部分所定义),则可能需要优化百分比转义。 值得注意的是,虽然&+在URL中是有效的字符,但它们在URL查询参数值中无效(因为&被用作查询参数之间的分隔符,这会过早地终止您的值,并将+转换为空格字符) 。 不幸的是,标准的百分比转义离开了这些分隔符。

因此,您可能希望百分号转义不在RFC 3986的未预留字符列表中的所有字符:

URI中允许使用但不具有保留目的的字符称为unreserved。 这些包括大写和小写字母,十进制数字,连字符,句号,下划线和代字号。

      unreserved = ALPHA / DIGIT /“ - ”/“。”  /“_”/“〜”

后来在3.4节,RFC进一步考虑添加?/到查询中允许的字符列表:

字符斜杠(“/”)和问号(“?”)可能代表查询组件中的数据。 注意,一些较老的,错误的实现可能无法正确处理这些数据,当它被用作相对引用的基本URI时(5.1节),显然是因为它们在查找分层分隔符时无法区分查询数据和path数据。 然而,由于查询组件经常用于以“key = value”对的forms携带标识信息,而一个常用的值是对另一个URI的引用,所以有时为了可用性避免百分比编码这些字符更好。

因此,您可以定义一个string扩展名:

 extension String { /// Returns a new string made from the `String` by replacing all characters not in the unreserved /// character set (As defined by RFC3986) with percent encoded characters. func stringByAddingPercentEncodingForURLQueryParameter() -> String? { let allowedCharacters = NSCharacterSet.URLQueryParameterAllowedCharacterSet() return stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacters) } } 

哪里

 extension NSCharacterSet { /// Returns the character set for characters allowed in the individual parameters within a query URL component. /// /// The query component of a URL is the component immediately following a question mark (?). /// For example, in the URL `http://www.example.com/index.php?key1=value1#jumpLink`, the query /// component is `key1=value1`. The individual parameters of that query would be the key `key1` /// and its associated value `value1`. /// /// According to RFC 3986, the set of unreserved characters includes /// /// `ALPHA / DIGIT / "-" / "." / "_" / "~"` /// /// In section 3.4 of the RFC, it further recommends adding `/` and `?` to the list of unescaped characters /// for the sake of compatibility with some erroneous implementations, so this routine also allows those /// to pass unescaped. class func URLQueryParameterAllowedCharacterSet() -> Self { return self.init(charactersInString: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~/?") } } 

然后你可以使用这个新function(例如,假设我正在寻找“华盛顿和李大学”):

 let address = "Washington & Lee University" let escapedAddress = address.stringByAddingPercentEncodingForURLQueryParameter() ?? "" let url = NSURL(string: "http://maps.googleapis.com/maps/api/geocode/json?address=\(escapedAddress)") 

顺便说一下,虽然在上述的RFC中没有考虑到,W3C HTML规范的4.10.22.6节(URL编码的表单数据)表示application/x-www-form-urlencoded请求也应该用+字符replace空格字符并且在不应该被转义的字符中包括星号),因此:

 extension String { /// Returns a new string made from the `String` by replacing all characters not in the unreserved /// character set (as defined by W3C HTML specification for `application/x-www-form-urlencoded` /// requests) with percent encoded characters. func stringByAddingPercentEncodingForFormUrlencoded() -> String? { let allowedCharacters = NSMutableCharacterSet.URLQueryParameterAllowedCharacterSet() allowedCharacters.addCharactersInString(" ") return stringByAddingPercentEncodingWithAllowedCharacters(allowedCharacters)?.stringByReplacingOccurrencesOfString(" ", withString: "+") } } 

在实践中,Web服务很less关心这些空间是以百分比转义还是以+字符replace。

Swift 2.0

 let needsLove = "string needin some URL love" let safeURL = needsLove.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())! 

有用的Progamming技巧和黑客

URLQueryAllowedCharacterSet不应该用于查询参数的URL编码,因为这个字符集包含& URLQueryAllowedCharacterSet/等作为分隔符在URL查询,例如

 /?paramname=paramvalue&paramname=paramvalue 

这些字符在整个URL查询中是允许的,但不能在参数值中使用。

RFC 3986专门讨论了不同于允许的未保留字符:

2.3。 未保留的字符

URI中允许使用的字符,但没有保留字符
目的被称为毫无保留。 这些包括大写和小写字母,十进制数字,连字符,句号,下划线和代字号。

  unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" 

因此:

 extension String { var URLEncoded:String { let unreservedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" let unreservedCharset = NSCharacterSet(charactersInString: unreservedChars) let encodedString = self.stringByAddingPercentEncodingWithAllowedCharacters(unreservedCharset) return encodedString ?? self } } 

上面的代码不会调用alphanumericCharacterSet因为它返回的字符集的大小(103806个字符)。 鉴于alphanumericCharacterSet字符集有多less个Unicode字符允许,使用它来进行URL编码的目的是错误的。

用法:

 let URLEncodedString = myString.URLEncoded 

XCODE 8,SWIFT 3.0

从grokswift

从string创buildURL是一个错误的雷区。 只是错过一个/或意外的URL编码? 在查询中,您的API调用将失败,您的应用程序将不会显示任何数据(甚至在您没有预料到可能的情况下会崩溃)。 从iOS 8开始,使用NSURLComponentsNSURLQueryItems更好地构buildURL。

 func createURLWithComponents() -> URL? { var urlComponents = URLComponents() urlComponents.scheme = "http" urlComponents.host = "maps.googleapis.com" urlComponents.path = "/maps/api/geocode/json" let addressQuery = URLQueryItem(name: "address", value: "American Tourister, Abids Road, Bogulkunta, Hyderabad, Andhra Pradesh, India") urlComponents.queryItems = [addressQuery] return urlComponents.url } 

以下是使用guard语句访问url的代码。

 guard let url = createURLWithComponents() else { print("invalid URL") return nil } print(url) 

输出:

 http://maps.googleapis.com/maps/api/geocode/json?address=American%20Tourister,%20Abids%20Road,%20Bogulkunta,%20Hyderabad,%20Andhra%20Pradesh,%20India 

阅读更多: 使用NSURLComponents和NSURLQueryItems构buildURL

在Mac OS 10.9 Maverics和iOS 7中,已经引入了NSURLComponents ,它以相当便利的方式处理不同URL部分的编码。

NSURLComponents类是一个类,它被devise来parsing基于RFC 3986的URL,并从它们的组成部分构buildURL。 它的行为与NSURL类有细微的差别,符合较旧的RFC。 但是,您可以根据URL组件对象的内容轻松获取NSURL对象,反之亦然。

 let address = "American Tourister, Abids Road, Bogulkunta, Hyderabad, Andhra Pradesh, India" let components = NSURLComponents(string: "http://maps.googleapis.com/maps/api/geocode/json")! // create a query item key=value let queryItem = NSURLQueryItem(name: "address", value: address) // add the query item to the URL, NSURLComponents takes care of adding the question mark. components.queryItems = [queryItem] // get the properly percent encoded string let urlpath = components.string! print(urlpath) 

更新了Swift 3:

 var escapedAddress = address.addingPercentEncoding( withAllowedCharacters: CharacterSet.urlQueryAllowed) 

只要完成Desmond Hume的答案就可以扩展RFC 3986非保留字符有效编码函数的String类(如果您正在编码查询FORM参数,则需要):

Swift 3

 extension String { var RFC3986UnreservedEncoded:String { let unreservedChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~" let unreservedCharsSet: CharacterSet = CharacterSet(charactersIn: unreservedChars) let encodedString: String = self.addingPercentEncoding(withAllowedCharacters: unreservedCharsSet)! return encodedString } } 

在我的情况下,最后一个组件是非拉丁字符,我在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; } } 

在上面Bryan Chen的回答中join:

只要告诉其他人正在得到与Alamofire类似的东西:

错误:Alamofire编译优化 – 步进可能performance怪异; variables可能不可用。

这不是一个非常具有描述性的错误。 在构buildGoogle地理位置服务的url时,我遇到了这个错误。 我在URL的末尾添加了一个街道地址,而没有先编码街道地址。 我能用Bryan Chen的解决scheme来解决它:

 var streetAdress = "123 fake street, new york, ny" var escapedStreetAddress = streetAddress.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet()) let url = "\(self.baseUrl)&address=\(escapedAddress!)" 

为我修好了! 它不是那个地址有空格和逗号等等

希望这可以帮助别人!