web-dev-qa-db-fra.com

Comment encoder une URL dans Swift

Ceci est ma URL

Le problème est que le champ address n'est pas ajouté à urlpath.

Est-ce que quelqu'un sait pourquoi c'est?

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

Utilisez stringByAddingPercentEncodingWithAllowedCharacters

var escapedAddress = address.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())

Utilisez stringByAddingPercentEscapesUsingEncoding: Déconseillé dans iOS 9 et 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)")
181
Bryan Chen

S'il est possible que la valeur que vous ajoutez à votre URL puisse avoir des caractères réservés (comme défini dans la section 2 de RFC 3986 ), vous devrez peut-être affiner votre échappement à pourcentage. Notamment, alors que & et + sont des caractères valides dans une URL, ils ne sont pas valides dans une valeur de paramètre de requête d'URL (car & est utilisé comme séparateur entre des paramètres de requête qui mettraient fin prématurément à votre valeur, et + est traduit en espace). . Malheureusement, le pourcentage standard de fuite laisse ces délimiteurs sans échappatoire.

Ainsi, vous voudrez peut-être échapper en pourcentage tous les caractères qui ne figurent pas dans la liste des caractères non réservés de la RFC 3986: 

Caractères autorisés dans un URI mais n'ayant pas de réservé but sont appelés sans réserve. Ceux-ci incluent les majuscules et les minuscules lettres, chiffres décimaux, trait d'union, point, trait de soulignement et tilde.

 sans réserve = ALPHA/DIGIT/"-"/"."/"_"/"~" 

Plus tard, dans la section 3.4, la RFC envisage en outre d'ajouter ? et / à la liste des caractères autorisés dans une requête:

Les caractères barre oblique ("/") et le point d'interrogation ("?") Peuvent représenter des données dans le composant de requête. Attention, certains plus vieux, erronés les implémentations peuvent ne pas gérer correctement ces données lorsqu'elles sont utilisées en tant que l'URI de base pour les références relatives (Section 5.1), apparemment car ils ne parviennent pas à distinguer les données de requête des données de chemin lorsque à la recherche de séparateurs hiérarchiques. Cependant, en tant que composants de requête sont souvent utilisés pour transporter des informations d'identification sous la forme de "clé = valeur" paires et une valeur fréquemment utilisée est une référence à Pour un autre URI, il est parfois préférable, pour des raisons de convivialité, d’éviter les pourcentages - encoder ces caractères.

De nos jours, vous utiliseriez généralement URLComponents pour échapper à la valeur de la requête:

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!

En passant, bien que cela ne soit pas envisagé dans la RFC susmentionnée, le section 4.10.22.6, données de formulaire codées par URL } de la spécification HTML du W3C indique que les demandes application/x-www-form-urlencoded doivent également remplacer les caractères espace par les caractères + l'astérisque dans les caractères à ne pas échapper). Et, malheureusement, URLComponents n'échappera pas correctement à ce problème. Apple vous conseille donc de le faire manuellement avant de récupérer la propriété url de l'objet URLComponents:

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

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

Pour le rendu de Swift 2, où je fais manuellement tout ce pour cent échapper moi-même, voir le révision précédente de cette réponse .

62
Rob

Swift 3:

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

Swift 2.0

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

Conseils et astuces de programmation utiles

33
quemeful

URLQueryAllowedCharacterSet ne doit pas être utilisé pour le codage d’URL des paramètres de requête, car ce jeu de caractères inclut &, ?, / etc. qui servent de délimiteurs dans une requête d’URL, par exemple.

/?paramname=paramvalue&paramname=paramvalue

Ces caractères sont autorisés dans les requêtes d'URL dans leur ensemble, mais pas dans les valeurs de paramètre.

La RFC 3986 parle spécifiquement des caractères non réservés, qui sont différents des caractères autorisés:

2.3. Caractères non réservés

Caractères autorisés dans un URI mais n'ayant pas de caractère réservé
but sont appelés sans réserve. Ceux-ci incluent les majuscules et les minuscules lettres, chiffres décimaux, trait d'union, point, trait de soulignement et tilde.

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

En conséquence:

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

Le code ci-dessus n'appelle pas alphanumericCharacterSet en raison de la taille énorme du jeu de caractères qu'il renvoie (103806 caractères). Et compte tenu du nombre de caractères Unicode que alphanumericCharacterSet permet, son utilisation à des fins de codage d'URL serait tout simplement erronée.

Usage:

let URLEncodedString = myString.URLEncoded
10
Desmond Hume

Swift 4.1

Créez un "jeu de caractères" en fonction de l'option souhaitée (urlQueryAllowed). Supprimez ensuite les caractères supplémentaires que vous ne voulez pas (+ &). Puis passez ce jeu de caractères à "addedPercentEncoding".

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

De grokswift

La création d'URL à partir de chaînes est un terrain miné pour les bugs. Il suffit de manquer un seul/ou accidentellement URL encoder le? Dans une requête, votre appel d'API échouera et votre application n'aura pas de données à afficher (ou même se bloquerait si vous n'aviez pas anticipé cette possibilité). _ {Depuis iOS 8, il existe un meilleur moyen de créer des URL en utilisant NSURLComponents et NSURLQueryItems. 

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
}

Voici le code pour accéder à l'URL à l'aide de l'instruction guard.

guard let url = createURLWithComponents() else {
            print("invalid URL")
            return nil
      }
      print(url)

Sortie: 

http://maps.googleapis.com/maps/api/geocode/json?address=American%20Tourister,%20Abids%20Road,%20Bogulkunta,%20Hyderabad,%20Andhra%20Pradesh,%20India

En savoir plus: Création d'URL avec NSURLComponents et NSURLQueryItems

6
Ashok R

Mise à jour pour Swift 3:

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

Dans Mac OS 10.9, Maverics et iOS 7 ont été introduits dans NSURLComponents, qui gère l'encodage des différentes parties d'URL de manière très pratique.

La classe NSURLComponents est une classe conçue pour analyser les URL basé sur la RFC 3986 et de construire des URL à partir de leurs éléments constitutifs . Son comportement diffère légèrement de la classe NSURL, qui se conforme à anciennes RFC. Cependant, vous pouvez facilement obtenir un objet NSURL basé sur le contenu d'un objet composants URL ou vice versa.

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

En complétant simplement la réponse de Desmond Hume pour étendre la classe String pour un fonction de codage valide RFC 3986 non réservée (nécessaire si vous codez des paramètres FORM de requête):

Swift 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

J'avais besoin de coder mes paramètres avec ISO-8859-1, donc la méthode addPercentEncoding () ne fonctionne pas pour moi .

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
  }

}

Usage:

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

Ajoutant à la réponse de Bryan Chen ci-dessus:

Au cas où quelqu'un d'autre obtiendrait quelque chose de similaire avec Alamofire:

erreur: Alamofire a été compilé avec optimisation - la progression peut se comporter étrangement; les variables peuvent ne pas être disponibles.

Ce n'est pas une erreur très descriptive. Je recevais cette erreur lors de la construction d'une URL pour les services Google Geo. J'ajoutais une adresse postale à la fin de l'URL SANS encoder d'abord l'adresse postale elle-même. J'ai pu résoudre le problème en utilisant la solution de Bryan Chen:

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

Cela l'a corrigé pour moi! Il n'a pas aimé que l'adresse avait des espaces et des virgules, etc.

J'espère que ceci aide quelqu'un d'autre!

0
Geoherna