如何在Swift中编码URL

问题描述 投票:120回答:13

这是我的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)")
ios swift urlencode
13个回答
187
投票

Swift 4.2

var urlString = originalString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

Swift 3.0

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)")

使用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)")

2
投票

刚刚完成Desmond Hume的答案,扩展String类的RFC 3986无保留字符有效编码功能(如果您编码查询FORM参数,则需要):

斯威夫特3

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)

0
投票

除了Bryan Chen的答案之外:

只是让其他人得到与Alamofire相似的东西:

错误:Alamofire是通过优化编译的 - 步进可能表现得很奇怪;变量可能无法使用。

这不是一个非常描述性的错误。在为Google地理服务构建网址时,我遇到了这个错误。我在URL的末尾附加了一个街道地址,没有首先编码街道地址本身。我能够使用Bryan Chen的解决方案修复它:

extension String {

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

那为我修好了!它不喜欢地址有空格和逗号等。

希望这有助于其他人!


0
投票

我需要使用ISO-8859-1对参数进行编码,因此addsPercentEncoding()方法对我不起作用。我在Swift 4中解决了我的问题:

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

用法:

extension String {

  // Url percent encoding according to RFC3986 specifications
  // https://tools.ietf.org/html/rfc3986#section-2.1
  func urlPercentEncoded(withAllowedCharacters allowedCharacters: 
    CharacterSet, encoding: String.Encoding) -> String {
    var returnStr = ""

    // Compute each char seperatly
    for char in self {
      let charStr = String(char)
      let charScalar = charStr.unicodeScalars[charStr.unicodeScalars.startIndex]
      if allowedCharacters.contains(charScalar) == false,
        let bytesOfChar = charStr.data(using: encoding) {
        // Get the hexStr of every notAllowed-char-byte and put a % infront of it, append the result to the returnString
        for byte in bytesOfChar {
          returnStr += "%" + String(format: "%02hhX", byte as CVarArg)
        }
      } else {
        returnStr += charStr
      }
    }

    return returnStr
  }

}

-1
投票

在我的情况下,最后一个组件是非拉丁字符我在"aouäöü!".urlPercentEncoded(withAllowedCharacters: .urlQueryAllowed, encoding: .isoLatin1) // Results in -> "aou%E4%F6%FC!" 中执行了以下操作:

Swift 2.2

66
投票

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

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

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

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

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

字符斜杠(“/”)和问号(“?”)可以表示查询组件中的数据。请注意,当某些较旧的错误实现用作相对引用的基本URI时,可能无法正确处理此类数据(第5.1节),这显然是因为它们在查找分层分隔符时无法区分查询数据和路径数据。但是,由于查询组件通常用于携带“key = value”对形式的标识信息,而一个常用值是对另一个URI的引用,因此有时可以更好地避免对这些字符进行百分比编码。

如今,你通常使用URLComponents来逃避查询值:

var address = "American Tourister, Abids Road, Bogulkunta, Hyderabad, Andhra Pradesh, India"
var components = URLComponents(string: "http://maps.googleapis.com/maps/api/geocode/json")!
components.queryItems = [URLQueryItem(name: "address", value: address)]
let url = components.url!

顺便说一句,虽然在上述RFC中没有考虑到,但是W3C HTML规范的section 5.2, URL-encoded form dataapplication/x-www-form-urlencoded请求也应该用+字符替换空格字符(并且在不应该转义的字符中包含星号)。并且,不幸的是,URLComponents将无法正确地逃避这一点,因此Apple建议您在检索url对象的URLComponents属性之前手动百分之以逃避它:

// configure `components` as shown above, and then:

components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
let url = components.url!

对于Swift 2的演绎,我手动完成所有这些百分比逃脱,请参阅previous revision of this answer


62
投票

斯威夫特3:

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

33
投票

Swift 2.0

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

Helpful Progamming Tips and Hacks


11
投票

URLQueryAllowedCharacterSet不应该用于查询参数的URL编码,因为这个charset包括&?/等,它们在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允许使用多少个Unicode字符,将其用于URL编码的目的只是错误的。

用法:

let URLEncodedString = myString.URLEncoded

6
投票

XCODE 8,SWIFT 3.0

来自grokswift

从字符串创建URL是bug的一个雷区。只是错过一个/或不小心的URL编码?在查询中,您的API调用将失败,您的应用程序将不会显示任何数据(如果您没有预料到这种可能性,甚至会崩溃)。从iOS 8开始,有一种更好的方法可以使用NSURLComponentsNSURLQueryItems构建URL。

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

阅读更多:Building URLs With NSURLComponents and NSURLQueryItems


6
投票

Swift 4.1

根据您想要的选项(urlQueryAllowed)创建“字符集”。然后删除您不想要的其他字符(+&)。然后将该字符集传递给“addingPercentEncoding”。

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

4
投票

针对Swift 3进行了更新:

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

3
投票

在Mac OS 10.9 Mavericks和iOS 7中引入了qazxsw poi,它以非常方便的方式处理不同URL部分的编码。

NSURLComponents类是一个用于解析基于RFC 3986的URL并从其组成部分构造URL的类。它的行为与NSURL类略有不同,后者符合较旧的RFC。但是,您可以根据URL组件对象的内容轻松获取NSURL对象,反之亦然。

NSURLComponents
© www.soinside.com 2019 - 2024. All rights reserved.