web-dev-qa-db-ja.com

Swift - URLをエンコード

このような文字列をエンコードすると、

var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

スラッシュ/をエスケープしません。

Objective Cのコードを検索しました。

NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                        NULL,
                        (CFStringRef)unencodedString,
                        NULL,
                        (CFStringRef)@"!*'();:@&=+$,/?%#[]",
                        kCFStringEncodingUTF8 );

URLをエンコードするより簡単な方法はありますか?そうでない場合、Swiftでこれをどのように書くのですか?

250
MegaCookie

スイフト3

Swift 3にはaddingPercentEncodingがあります

let originalString = "test/test"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(escapedString!)

出力:

テスト%2Ftest

スイフト1

IOS 7以降ではstringByAddingPercentEncodingWithAllowedCharactersがあります

var originalString = "test/test"
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
println("escapedString: \(escapedString)")

出力:

テスト%2Ftest

以下は便利な(反転)文字セットです。

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

別の文字セットをエスケープしたい場合は、セットを作成します。
"="文字を追加した例:

var originalString = "test/test=42"
var customAllowedSet =  NSCharacterSet(charactersInString:"=\"#%/<>?@\\^`{|}").invertedSet
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedSet)
println("escapedString: \(escapedString)")

出力:

テスト%2Fテスト%3D42

セットに含まれていないASCII文字を検証する例:

func printCharactersInSet(set: NSCharacterSet) {
    var characters = ""
    let iSet = set.invertedSet
    for i: UInt32 in 32..<127 {
        let c = Character(UnicodeScalar(i))
        if iSet.longCharacterIsMember(i) {
            characters = characters + String(c)
        }
    }
    print("characters not in set: \'\(characters)\'")
}
522
zaph

URLComponentsを使用すると、クエリ文字列を手動でパーセントエスケープする必要がなくなります。

let scheme = "https"
let Host = "www.google.com"
let path = "/search"
let queryItem = URLQueryItem(name: "q", value: "Formula One")


var urlComponents = URLComponents()
urlComponents.scheme = scheme
urlComponents.Host = Host
urlComponents.path = path
urlComponents.queryItems = [queryItem]

if let url = urlComponents.url {
    print(url)   // "https://www.google.com/search?q=Formula%20One"
}

extension URLComponents {
    init(scheme: String = "https",
         Host: String = "www.google.com",
         path: String = "/search",
         queryItems: [URLQueryItem]) {
        self.init()
        self.scheme = scheme
        self.Host = Host
        self.path = path
        self.queryItems = queryItems
    }
}

let query = "Formula One"
if let url = URLComponents(queryItems: [URLQueryItem(name: "q", value: query)]).url {
    print(url)  // https://www.google.com/search?q=Formula%20One
}
46
Leo Dabus

スイフト3:

let allowedCharacterSet = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)

if let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) {
//do something with escaped string
}
32
Hong Wei

スイフト3:

let originalString = "http://www.ihtc.cc?name=htc&title=iOS开发工程师"

1. encodingQuery:

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

結果:

"http://www.ihtc.cc?name=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88" 

2. encodingURL:

let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

結果:

"http:%2F%2Fwww.ihtc.cc%3Fname=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88"
23
iHTCboy

スイフト4

URLでパラメータをエンコードするには、.alphanumerics文字セットを使って最も簡単なオプションを設定します。

let encoded = parameter.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
let url = "http://www.example.com/?name=\(encoded!)"

URLエンコードに標準の文字セット(URLQueryAllowedCharacterSetURLHostAllowedCharacterSetなど)を使用しても、=&の文字が除外されないため、機能しません。

.alphanumericsを使用すると、エンコードする必要がない一部の文字がエンコードされます(-._~のいずれか - RFC 2.386の2.3参照。未予約の文字)。私は.alphanumericsを使うことはカスタム文字セットを構築することよりも簡単であり、追加の文字をエンコードしても構わないと思います。それが気になる場合は、 URL String をパーセントエンコードする方法で説明されているように、カスタム文字セットを作成してください。次に例を示します。

var allowed = CharacterSet.alphanumerics
allowed.insert(charactersIn: "-._~") // as per RFC 3986
let encoded = parameter.addingPercentEncoding(withAllowedCharacters: allowed)
let url = "http://www.example.com/?name=\(encoded!)"

警告: encodedパラメータは強制的にアンラップされています。無効なUnicode文字列の場合はクラッシュする可能性があります。 を参照してください。String.addingPercentEncoding()の戻り値はオプションなのですか。encoded!を強制的にアンラップする代わりに、encoded ?? ""を使うかif let encoded = ...を使うことができます。

16
Marián Černý

すべてが同じ

var str = CFURLCreateStringByAddingPercentEscapes(
    nil,
    "test/test",
    nil,
    "!*'();:@&=+$,/?%#[]",
    CFStringBuiltInEncodings.UTF8.rawValue
)

// test%2Ftest
12
Bryan Chen

Swift 4(テストされていません - 動作するかどうかをコメントしてください。提案してくれてありがとう@sumizome)

var allowedQueryParamAndKey = NSCharacterSet.urlQueryAllowed
allowedQueryParamAndKey.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

スイフト3

let allowedQueryParamAndKey =  NSCharacterSet.urlQueryAllowed.remove(charactersIn: ";/?:@&=+$, ")
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)

Swift 2.2 (Zaphから借りてURLクエリキーとパラメータ値を修正する)

var allowedQueryParamAndKey =  NSCharacterSet(charactersInString: ";/?:@&=+$, ").invertedSet
paramOrKey.stringByAddingPercentEncodingWithAllowedCharacters(allowedQueryParamAndKey)

例:

let paramOrKey = "https://some.website.com/path/to/page.srf?a=1&b=2#top"
paramOrKey.addingPercentEncoding(withAllowedCharacters: allowedQueryParamAndKey)
// produces:
"https%3A%2F%2Fsome.website.com%2Fpath%2Fto%2Fpage.srf%3Fa%3D1%26b%3D2%23top"

これはBryan Chenの答えの短いバージョンです。私はurlQueryAllowedが制御文字を許容しているのではないかと思っています。それは、それらがエスケープする必要がある時点でクエリ文字列内のキーまたは値の一部を形成しない限り。

10
AJP

スイフト4:

それはあなたのサーバが従うエンコーディング規則によって異なります。

Appleはこのクラスメソッドを提供していますが、それが従うどんな種類のRCFプロトコルも報告しません。

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!

この便利な tool に従うと、あなたはあなたのパラメータのためにこれらの文字のエンコーディングを保証するべきです:

  • $(ドル記号)は%24になります
  • &(アンパサンド)は%26になります
  • +(プラス)は%2Bになります
  • 、(カンマ)は%2Cになります
  • :(コロン)は%3Aになります
  • ; (セミコロン)は%3Bになります
  • =(等しい)は%3Dになります
  • ? (疑問符)は%3Fになります
  • @(コマーシャルA/At)は%40になります

言い換えれば、URLエンコーディングについて言えば、 RFC 1738プロトコルに従うべきです

そしてSwiftは のような+ charのエンコーディングをカバーしていませんが、これら3つの @ではうまくいきます。 chars。

したがって、各パラメータを正しくエンコードするには、.urlHostAllowedオプションでは不十分です。たとえば、次のように特殊文字も追加する必要があります。

encodedParameter = parameter.replacingOccurrences(of: "+", with: "%2B")

これが、これらの情報を検索するのに夢中になる人に役立つことを願っています。

8

私自身がこれを必要としていたので、URLEncoding文字列と、より一般的な最終目標である "辞書"を "GET"スタイルのURLパラメータに変換することを可能にするString拡張を書きました。

extension String {
    func URLEncodedString() -> String? {
        var escapedString = self.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
        return escapedString
    }
    static func queryStringFromParameters(parameters: Dictionary<String,String>) -> String? {
        if (parameters.count == 0)
        {
            return nil
        }
        var queryString : String? = nil
        for (key, value) in parameters {
            if let encodedKey = key.URLEncodedString() {
                if let encodedValue = value.URLEncodedString() {
                    if queryString == nil
                    {
                        queryString = "?"
                    }
                    else
                    {
                        queryString! += "&"
                    }
                    queryString! += encodedKey + "=" + encodedValue
                }
            }
        }
        return queryString
    }
}

楽しい!

4
BadPirate

これは私のために働いています。

func stringByAddingPercentEncodingForFormData(plusForSpace: Bool=false) -> String? {

    let unreserved = "*-._"
    let allowed = NSMutableCharacterSet.alphanumericCharacterSet()
    allowed.addCharactersInString(unreserved)

    if plusForSpace {
        allowed.addCharactersInString(" ")
    }

    var encoded = stringByAddingPercentEncodingWithAllowedCharacters(allowed)

    if plusForSpace {
        encoded = encoded?.stringByReplacingOccurrencesOfString(" ", withString: "+")
    }
    return encoded
}

私はこのリンクから上記の機能を見つけました: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string/

2
Gaurav Singla

スイフト4.2

簡単な1行ソリューションoriginalStringをエンコードしたいStringに置き換えます。

var encodedString = originalString.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]{} ").inverted)

オンラインプレイグラウンドデモ

1
ajzbc

スイフト4.2

たまにこれは、API URLを通過するパラメータのためのスラグORにURLエンコードの欠如があるために発生しました。

let myString = self.slugValue
                let csCopy = CharacterSet(bitmapRepresentation: CharacterSet.urlPathAllowed.bitmapRepresentation)
                let escapedString = myString!.addingPercentEncoding(withAllowedCharacters: csCopy)!
                //always "info:hello%20world"
                print(escapedString)

注:bitmapRepresentationについて探求することを忘れないでください。

0
Vrushal Raut