Swift - encoder l'URL

si JE CODE une chaîne comme celle-ci:

var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)

il n'échappe pas aux slashs / .

j'ai cherché et trouvé ce code objectif C:

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

y a-t-il un moyen plus simple d'encoder une URL et si ce n'est pas le cas, comment dois-je l'écrire dans Swift?

216
demandé sur Bryan Chen 2014-07-03 14:56:02

10 réponses

Swift 3

dans Swift 3 Il y a addingPercentEncoding

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

sortie:

test%2Ftest

Swift 1

En iOS 7 et il y a en haut stringByAddingPercentEncodingWithAllowedCharacters

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

sortie:

test%2Ftest

ce qui suit sont utiles (inversé) jeux de caractères:

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

si vous voulez qu'un ensemble différent de caractères soit échappé créer un ensemble:

Exemple avec le caractère "=" ajouté:

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

sortie:

test%2Ftest%3D42

exemple pour vérifier les caractères ascii ne figurant pas dans l'ensemble:

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)\'")
}
465
répondu zaph 2017-05-18 16:19:29

vous pouvez utiliser URLComponents pour éviter d'avoir à échapper manuellement pourcentage de votre chaîne de requête:

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, host: String, path: String, queryItems: [URLQueryItem]) {
        self.init()
        self.scheme = scheme
        self.host = host
        self.path = path
        self.queryItems = queryItems
    }
}

if let url = URLComponents(scheme: "https",
                             host: "www.google.com",
                             path: "/search",
                       queryItems: [URLQueryItem(name: "q", value: "Formula One")]).url {

    print(url)  // https://www.google.com/search?q=Formula%20One
}
36
répondu Leo Dabus 2017-05-12 10:57:31

Swift 3:

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

if let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) {
//do something with escaped string
}
30
répondu Hong Wei 2016-10-06 00:49:28

Swift 3:

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

1. encodingQuery:

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

résultat:

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

résultat:

"http:%2F%2Fwww.ihtc.cc%3Fname=htc&title=iOS%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88"
18
répondu iHTCboy 2017-05-19 18:19:59

tout est pareil

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

// test%2Ftest
11
répondu Bryan Chen 2014-10-16 23:42:30

Swift 4

pour encoder un paramètre dans L'URL je trouve en utilisant .alphanumerics jeu de caractères l'option la plus facile:

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

utilisant l'un des jeux de caractères standard pour le codage D'URL (comme URLQueryAllowedCharacterSet ou URLHostAllowedCharacterSet ) ne fonctionnera pas, parce qu'ils n'excluent pas = ou & caractères.

Note qu'en utilisant .alphanumerics il encodera certains caractères qui ne sont pas besoin d'être encodé (comme - , . , _ ou ~ -- voir 2.3. Caractères non réservés dans la RFC 3986). Je trouve l'utilisation de .alphanumerics plus simple que la construction d'un jeu de caractères personnalisé et ne me dérange pas certains caractères supplémentaires à encoder. Si cela vous dérange, construisez un jeu de caractères personnalisé comme est décrit dans comment coder en pourcentage une chaîne D'URL , comme par exemple:

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

Avertissement: Le encoded paramètre est la force déballé. Pour une chaîne unicode invalide, il pourrait se planter. Voir Pourquoi est la valeur de retour de la chaîne.addingPercentEncoding () optional? . Au lieu de déballer la force encoded! , vous pouvez utiliser encoded ?? "" ou if let encoded = ... .

11
répondu Marián Černý 2018-09-26 03:09:44

Swift 4 (non testé - veuillez commenter si cela fonctionne ou non. Merci @sumizome pour la suggestion)

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

Swift 3

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

Swift 2.2 (emprunt auprès de Zaph et correction des valeurs des clés et des paramètres des requêtes url)

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

exemple:

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"

C'est un version abrégée de la réponse de Bryan Chen. Je suppose que urlQueryAllowed permet les caractères de contrôle par lequel est très bien sauf s'ils font partie de la clé ou de la valeur dans votre chaîne de requête à quel point ils doivent être échappés.

8
répondu AJP 2018-09-26 07:05:58

Swift 4:

cela dépend des règles d'encodage suivies par votre serveur.

Apple offre cette méthode de classe, mais il ne rend pas compte du type de protocole RCF qu'il suit.

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

après cet utile outil vous devez garantir l'encodage de ces caractères pour vos paramètres:

  • $ (signe Dollar) devient %24
  • & (Ampersand) devient %26
  • + (Plus) devient %2B
  • , (virgule) devient %2C
  • : (Colon) devient % 3A
  • ; (Semi-Colon) devient %3B
  • = (égal) devient % 3D
  • ? (Point d'interrogation) devient %3F
  • @ (Commercial A / At) devient % 40

en d'autres termes, en parlant D'encodage URL, vous devriez suite au RFC 1738 protocole .

et Swift ne couvrent pas l'encodage du + char par exemple , mais cela fonctionne bien avec ces trois @:? chars.

ainsi, pour encoder correctement chacun de vos paramètres , l'option .urlHostAllowed n'est pas suffisante, vous devez ajouter aussi les caractères spéciaux comme par exemple:

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

Espérons que cela aide quelqu'un qui devenez fou de rechercher ces informations.

5
répondu Alessandro Ornano 2018-03-10 07:42:52

avait besoin de cela moi-même, donc j'ai écrit une extension de chaîne qui permet à la fois des chaînes URLEncoding, ainsi que le but final plus commun, la conversion d'un dictionnaire de paramètres en" GET "style URL Parameters:

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
    }
}

Profitez-en!

3
répondu BadPirate 2016-10-11 18:54:19

celui-ci travaille pour moi.

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
}

j'ai trouvé la fonction ci-dessus à partir de ce lien: http://useyourloaf.com/blog/how-to-percent-encode-a-url-string / .

2
répondu Gaurav Singla 2016-10-20 19:32:11