web-dev-qa-db-ja.com

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

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)")
185
Bryan Chen

URLに追加した値に予約文字が含まれる可能性がある場合( RFC 3986 のセクション2で定義されているように)、パーセントエスケープを調整する必要があるかもしれません。特に、&+はURL内では有効な文字ですが、URLクエリパラメータ値内では無効です(&はクエリパラメータ間の区切り文字として使用され、値が途中で終了し、+はスペース文字に変換されます)。 。残念ながら、標準的なパーセントエスケープでは、これらの区切り文字はエスケープされません。

したがって、RFC 3986の予約されていない文字のリストに含まれていないすべての文字をパーセントエスケープすることをお勧めします。

URIで許可されているが予約された目的を持たない文字は予約されていないと呼ばれます。これらには、大文字と小文字、10進数、ハイフン、ピリオド、アンダースコア、チルダが含まれます。

未予約= 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!

ところで、前述のRFCでは考えられていませんが、W3C HTML仕様の 5.2節、URLエンコードされたフォームデータ では、application/x-www-form-urlencodedリクエストはスペース文字を+文字で置き換えるべきです(そしてエスケープしてはいけない文字にアスタリスクを付けます。そして残念ながら、URLComponentsはこれを適切にパーセントエスケープしないので、urlオブジェクトのURLComponentsプロパティを取得する前に、手動でパーセントエスケープすることをお勧めします。

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

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

私が手作業でこのパーセントを自分でエスケープするSwift 2の表現については、 この回答の前の改訂 を参照してください。

64
Rob

Swift 3:

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

Swift 2.0

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

役立つプログラミングのヒントとハック

33
quemeful

この文字セットには、URLクエリの区切り文字として機能する&?/などが含まれるため、URLQueryAllowedCharacterSetをクエリパラメータのURLエンコードに使用しないでください。

/?paramname=paramvalue&paramname=paramvalue

これらの文字はURLクエリ全体では使用できますが、パラメータ値では使用できません。

RFC 3986 は、特に予約されていない文字について説明しています。

2.3。予約されていない文字

URIで許可されているが予約済みではない文字
目的は予約されていないと呼ばれます。これらには、大文字と小文字、10進数、ハイフン、ピリオド、アンダースコア、チルダが含まれます。

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

したがって:

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

上記のコードは、返される文字セットのサイズが非常に大きいため(103806文字)、alphanumericCharacterSetを呼び出しません。そしてalphanumericCharacterSetがどれだけの数のUnicode文字を許容するかを考えると、URLエンコードの目的でそれを使用することは単純に間違っているでしょう。

使用法:

let URLEncodedString = myString.URLEncoded
11
Desmond Hume

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

XCODE 8、Swift 3.0

grokswiftから

文字列からURLを作成することはバグの地雷原です。ただ1つまたは/または誤ってURLエンコードを見逃していませんか?クエリを実行するとAPI呼び出しが失敗し、アプリに表示するデータがなくなります(またはその可能性が予想されない場合はクラッシュします)。 iOS 8以降、NSURLComponentsおよびNSURLQueryItemsを使用して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

続きを読む: NSURLComponentsとNSURLQueryItemを使ったURLの構築

6
Ashok R

Swift 3用に更新されました。

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

Mac OS 10.9 MavericsおよびiOS 7では、さまざまなURL部分のエンコーディングを非常に便利な方法で処理するNSURLComponentsが導入されました。

NSURLComponentsクラスは、RFC 3986に基づいてURLを解析し、それらの構成部分からURLを構築するように設計されているクラスです。その振る舞いは、古いRFCに準拠しているNSURLクラスとは微妙に異なります。ただし、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)
3
vadian

RFC 3986予約されていない文字有効なエンコーディング関数(クエリのFORMパラメータをエンコーディングしている場合に必要)のStringクラスを拡張するためのDesmond Humeの回答を完成させたところです。

スイフト3

extension String {

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

私はISO-8859-1で私のパラメータをエンコードする必要がありました、それでAddingPercentEncoding()メソッドは私のために働かない。私は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!"
0
2h4u

上記のBryan Chenの回答に追加します。

他の誰かがAlamofireと似たようなものを手に入れているのなら、ただのことだ。

エラー:Alamofireは最適化されてコンパイルされています - ステッピングは奇妙に振る舞うかもしれません。変数は利用できないかもしれません。

それは説明的なエラーではありません。 GoogleジオサービスのURLを作成するときにエラーが発生しました。最初に住所をエンコードせずにURLの末尾に住所を追加していました。 Bryan Chenの解決策を使って修正することができました。

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

それは私のためにそれを修正しました!住所にスペースやカンマなどが含まれているのは嫌でした。

これが他の誰かに役立つことを願っています!

0
Geoherna