如何在Swift中编码URL

时间:2014-07-22 05:35:37

标签: ios swift urlencode

这是我的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)")

13 个答案:

答案 0 :(得分:185)

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

答案 1 :(得分:64)

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

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

  

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

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

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

  

字符斜线(" /")和问号("?")可能代表数据      在查询组件中。要小心一些年纪大了,错了      当实现它时,实现可能无法正确处理这些数据      显然,相对引用的基URI(第5.1节)      因为他们无法区分查询数据和路径数据      寻找分层分隔符。但是,作为查询组件      通常用于携带形式的识别信息      "键=值"对和一个经常使用的值是对的引用      另一个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!

顺便说一下,虽然W3C HTML规范中上述RFC section 5.2, URL-encoded form data中没有考虑到这一点,但application/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

答案 2 :(得分:62)

斯威夫特3:

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

答案 3 :(得分:33)

Swift 2.0

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

Helpful Progamming Tips and Hacks

答案 4 :(得分:11)

URLQueryAllowedCharacterSet不应用于查询参数的网址编码,因为此字符集包含&?/等,用作网址查询中的分隔符,例如

/?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

答案 5 :(得分:6)

  

XCODE 8,SWIFT 3.0

来自grokswift

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

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语句访问网址的代码。

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 :(得分:6)

Swift 4.1

创建一个"字符集"基于您想要的选项(urlQueryAllowed)。然后删除您不想要的其他字符(+&)。然后将该字符集传递给" addsPercentEncoding"。

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

答案 7 :(得分:4)

针对Swift 3进行了更新:

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

答案 8 :(得分:3)

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

  

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

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)

答案 9 :(得分:2)

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

Swift 3

colNamesOutputFile=["PROGRAM_NAME", "TEST_GROUP", "NAME", "OFFER"]
inputDF=pd.read_csv(InputFile
, skiprows=1
, names=colNamesOutputFile
, converters={'PROGRAM_NAME': convert_to_string, 'TEST_GROUP': convert_to_string, 'NAME': convert_to_string, 'OFFER': convert_to_string}
, index_col=False)
inputDF1SUM = pd.DataFrame({'Count' : inputDF.groupby(['PROGRAM_NAME','TEST_GROUP']).size()}).reset_index()
inputDF2SUM = pd.DataFrame(inputDF.groupby('NAME')).reset_index()
inputDF3SUM = pd.DataFrame(inputDF.groupby('OFFER')).reset_index()
print(inputDF1SUM)
print(inputDF2SUM)
print(inputDF3SUM)

答案 10 :(得分:0)

在上面回答Bryan Chen的回答:

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

  

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

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

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

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

希望这有助于其他人!

答案 11 :(得分:0)

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

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
  }

}

用法:

"aouäöü!".urlPercentEncoded(withAllowedCharacters: .urlQueryAllowed,
                                         encoding: .isoLatin1) 
// Results in -> "aou%E4%F6%FC!"

答案 12 :(得分:-1)

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