如何在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())
使用 在iOS 9和OS X v10.11中弃用 stringByAddingPercentEscapesUsingEncoding:
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¶mname=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开始,使用NSURLComponents
和NSURLQueryItems
更好地构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!)"
为我修好了! 它不是那个地址有空格和逗号等等
希望这可以帮助别人!