390 Stimmen

Swift - URL codieren

Wenn ich einen String so kodiere:

var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

werden die Schrägstriche / nicht maskiert.

Ich habe gesucht und diesen Objective-C-Code gefunden:

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

Gibt es einen einfacheren Weg, eine URL zu codieren und wenn nicht, wie schreibe ich das in Swift?

730voto

zaph Punkte 110105

Swift 3

In Swift 3 gibt es addingPercentEncoding

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

Output:

test%2Ftest

Swift 1

In iOS 7 und höher gibt es stringByAddingPercentEncodingWithAllowedCharacters

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

Output:

test%2Ftest

Die folgenden sind nützliche (invertierte) Zeichensätze:

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

Wenn Sie möchten, dass eine andere Gruppe von Zeichen escaped wird, erstellen sie ein Set:
Beispiel mit hinzugefügtem "=" Zeichen:

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

Output:

test%2Ftest%3D42

Beispiel zur Überprüfung von Ascii-Zeichen, die nicht im Set enthalten sind:

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)\'")
}

105voto

Leo Dabus Punkte 215103

Sie können URLComponents verwenden, um zu vermeiden, dass Sie Ihre Abfragezeichenfolge manuell Prozent codieren müssen:

let scheme = "https"
let host = "www.google.com"
let path = "/search"
let queryItem = URLQueryItem(name: "q", value: "Formel Eins")

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=Formel%20Eins"
}

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 = "Formel Eins"
if let url = URLComponents(queryItems: [URLQueryItem(name: "q", value: query)]).url {
    print(url)  // https://www.google.com/search?q=Formel%20Eins
}

94voto

Marián Černý Punkte 13932

Swift 4 & 5

Um einen Parameter in der URL zu codieren, finde ich die Verwendung des .alphanumerics Zeichensatzes die einfachste Option:

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

Die Verwendung eines der standardmäßigen Zeichensätze für die URL-Codierung (wie .urlQueryAllowed oder .urlHostAllowed) funktioniert nicht, da sie die Zeichen = oder & nicht ausschließen.

Die Verwendung von URLComponents funktioniert auch nicht korrekt, weil es das Zeichen + nicht escapen.

Beachten Sie, dass durch die Verwendung von .alphanumerics einige Zeichen codiert werden, die nicht codiert werden müssen (wie -, ., _ oder ~ - siehe 2.3. Unreserved characters in RFC 3986). Ich finde die Verwendung von .alphanumerics einfacher als die Konstruktion eines eigenen Zeichensatzes und habe kein Problem damit, dass einige zusätzliche Zeichen codiert werden. Wenn Sie das stört, konstruieren Sie einen eigenen Zeichensatz, wie zum Beispiel in How to percent encode a URL String beschrieben:

// Speichern Sie den erlaubten Zeichensatz zur Wiederverwendung (lazy berechnet).
private let urlAllowed: CharacterSet =
    .alphanumerics.union(.init(charactersIn: "-._~")) // gemäß RFC 3986

extension String {
    var urlEncoded: String? {
        return addingPercentEncoding(withAllowedCharacters: urlAllowed)
    }
}

let url = "http://www.example.com/?name=\(value.urlEncoded!)"

Warnung: Der urlEncoded Parameter wird erzwungenermaßen entpackt. Bei ungültigen Unicode-Zeichenfolgen kann es abstürzen. Siehe Why is the return value of String.addingPercentEncoding() optional?. Anstatt urlEncoded! zu erzwingen, können Sie urlEncoded ?? "" oder if let urlEncoded = urlEncoded { ... } verwenden.

51voto

Hong Wei Punkte 1397

Swift 5:

extension String {
    var urlEncoded: String? {
        let allowedCharacterSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "~-_."))
        return self.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet)
    }
}

print("\u{48}ello\u{9}world\u{7}\u{0}".urlEncoded!) // prints Hello%09world%07%00
print("The string ü@foo-bar".urlEncoded!) // prints The%20string%20%C3%BC%40foo-bar

50voto

iHTCboy Punkte 2469

Swift 3:

let originalString = "http://www.ihtc.cc?name=htc&title=iOS"

1. encodingQuery:

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

result:

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

result:

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X