Si je code une chaîne comme ceci:
var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
il n'échappe pas aux barres obliques /
.
J'ai cherché et trouvé ce code Objective C:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );
Existe-t-il un moyen plus simple de coder une URL et si non, comment puis-je l'écrire dans Swift?
Dans Swift 3, il y a addingPercentEncoding
let originalString = "test/test"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(escapedString!)
Sortie:
test% 2Ftest
Dans iOS 7 et supérieur, il y a stringByAddingPercentEncodingWithAllowedCharacters
var originalString = "test/test"
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
println("escapedString: \(escapedString)")
Sortie:
test% 2Ftest
Voici des jeux de caractères utiles (inversés):
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}
URLHostAllowedCharacterSet "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet "#%<>[\]^`{|}
URLUserAllowedCharacterSet "#%/:<>?@[\]^`
Si vous souhaitez échapper un jeu de caractères différent, créez-en un:
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 qui ne sont pas dans le jeu:
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)\'")
}
Vous pouvez utiliser URLComponents pour éviter de devoir manuellement échapper le 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 = "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
}
Swift 3:
let allowedCharacterSet = (CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[] ").inverted)
if let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) {
//do something with escaped string
}
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"
Pour encoder un paramètre dans l'URL, l'utilisation du caractère .alphanumerics
est la plus simple:
let encoded = parameter.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
let url = "http://www.example.com/?name=\(encoded!)"
L'utilisation de l'un des jeux de caractères standard pour le codage d'URL (tels que URLQueryAllowedCharacterSet
ou URLHostAllowedCharacterSet
) ne fonctionnera pas, car ils n'excluent pas les caractères =
ou &
.
Notez qu'en utilisant .alphanumerics
, il encodera certains caractères qui n'ont pas besoin d'être encodés (comme -
, .
, _
ou ~
-– voir 2.3. Caractères non réservés dans RFC 3986). Je trouve que l'utilisation de .alphanumerics
est plus simple que de construire un jeu de caractères personnalisé et que certains caractères supplémentaires ne doivent pas être codés. Si cela vous dérange, construisez un jeu de caractères personnalisé comme décrit dans Comment encoder une URL par un pourcentage , 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 paramètre encoded
est forcé non emballé. Pour une chaîne unicode non valide, il peut se bloquer. Voir Pourquoi la valeur de retour de String.addingPercentEncoding () est-elle facultative? . Au lieu de forcer le déconditionnement de encoded!
, vous pouvez utiliser encoded ?? ""
ou utiliser if let encoded = ...
.
Tout est pareil
var str = CFURLCreateStringByAddingPercentEscapes(
nil,
"test/test",
nil,
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
// test%2Ftest
Swift 4 (non testé - veuillez indiquer si cela fonctionne ou non. Merci @sumizome pour vos suggestions)
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é à Zaph et corrigé pour la clé de requête et les valeurs de paramètre)
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"
Ceci est une version plus courte de la réponse de Bryan Chen. J'imagine que urlQueryAllowed
autorise les caractères de contrôle, ce qui est correct, à moins qu'ils ne fassent partie de la clé ou de la valeur de votre chaîne de requête à quel point ils doivent être ignorés.
Cela dépend des règles d'encodage suivies par votre serveur.
Apple propose cette méthode de classe, mais ne précise pas quel type de protocole RCF elle suit.
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
En suivant cet utile outil , vous devez garantir le codage de ces caractères pour vos paramètres:
En d'autres termes, en ce qui concerne le codage d'URL, vous devriez suivre le protocole RFC 1738 .
Et Swift ne couvre pas l'encodage du + caractère par exemple, mais cela fonctionne bien avec ces trois @:? caractères.
Donc, pour encoder correctement chacun de vos paramètres, l'option .urlHostAllowed
ne suffit pas, vous devez également ajouter les caractères spéciaux comme par exemple:
encodedParameter = parameter.replacingOccurrences(of: "+", with: "%2B")
J'espère que cela aide quelqu'un qui devient fou à rechercher ces informations.
J'avais besoin de cela moi-même, alors j'ai écrit une extension String qui permet à la fois de créer des chaînes URLEncoding, ainsi que l'objectif plus commun, convertir un dictionnaire de paramètres en style "GET"
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
}
}
Prendre plaisir!
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/ .
Une solution rapide en une ligne. Remplacez originalString
par la chaîne que vous souhaitez encoder.
var encodedString = originalString.addingPercentEncoding(withAllowedCharacters: CharacterSet(charactersIn: "!*'();:@&=+$,/?%#[]{} ").inverted)
Swift 4.2
Cela se produit parfois simplement parce qu'il y a de la place dans slug OR en l'absence de codage d'URL pour les paramètres transmis via l'URL de l'API.
let myString = self.slugValue
let csCopy = CharacterSet(bitmapRepresentation: CharacterSet.urlPathAllowed.bitmapRepresentation)
let escapedString = myString!.addingPercentEncoding(withAllowedCharacters: csCopy)!
//always "info:hello%20world"
print(escapedString)
NOTE: N'oubliez pas d'explorer environ bitmapRepresentation
.