Swift - codificar URL
Si codifico una cadena como esta:
var escapedString = originalString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
no escapa a las barras /
.
Busqué y encontré este código Objective C:
NSString *encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unencodedString,
NULL,
(CFStringRef)@"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8 );
¿Existe una forma más sencilla de codificar una URL y, de no ser así, cómo escribo esto en Swift?
veloz 3
En Swift 3 hayaddingPercentEncoding
let originalString = "test/test"
let escapedString = originalString.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)
print(escapedString!)
Producción:
prueba%2Fprueba
veloz 1
En iOS 7 y superior haystringByAddingPercentEncodingWithAllowedCharacters
var originalString = "test/test"
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
println("escapedString: \(escapedString)")
Producción:
prueba%2Fprueba
Los siguientes son conjuntos de caracteres útiles (invertidos):
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}
URLHostAllowedCharacterSet "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet "#%<>[\]^`{|}
URLUserAllowedCharacterSet "#%/:<>?@[\]^`
Si desea que se escape un conjunto diferente de caracteres, cree un conjunto:
Ejemplo con el carácter "=" agregado:
var originalString = "test/test=42"
var customAllowedSet = NSCharacterSet(charactersInString:"=\"#%/<>?@\\^`{|}").invertedSet
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(customAllowedSet)
println("escapedString: \(escapedString)")
Producción:
prueba%2Fprueba%3D42
Ejemplo para verificar caracteres ascii que no están en el conjunto:
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)\'")
}
Puede utilizar URLComponents para evitar tener que cifrar manualmente el porcentaje de su cadena de consulta:
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
}
Rápido 4 y 5
Para codificar un parámetro en una URL, creo que usar .alphanumerics
el juego de caracteres es la opción más sencilla:
let urlEncoded = value.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
let url = "http://www.example.com/?name=\(urlEncoded!)"
El uso de cualquiera de los conjuntos de caracteres estándar para la codificación de URL (como .urlQueryAllowed
o .urlHostAllowed
) no funcionará porque no excluyen =
caracteres &
.
El uso URLComponents
tampoco funciona correctamente porque no escapa al +
personaje.
Tenga en cuenta que al usarlo .alphanumerics
se codificarán algunos caracteres que no es necesario codificar (como -
, o -– consulte 2.3. Caracteres no reservados en RFC 3986). Considero que usar es más simple que construir un conjunto de caracteres personalizado y no me importa codificar algunos caracteres adicionales. Si eso le molesta, cree un conjunto de caracteres personalizado como se describe en Cómo codificar por ciento una cadena URL , como por ejemplo:.
_
~
.alphanumerics
// Store allowed character set for reuse (computed lazily).
private let urlAllowed: CharacterSet =
.alphanumerics.union(.init(charactersIn: "-._~")) // as per RFC 3986
extension String {
var urlEncoded: String? {
return addingPercentEncoding(withAllowedCharacters: urlAllowed)
}
}
let url = "http://www.example.com/?name=\(value.urlEncoded!)"
Advertencia: El urlEncoded
parámetro se desencapsula a la fuerza. Para una cadena Unicode no válida, podría fallar. Consulte ¿ Por qué el valor de retorno de String.addingPercentEncoding() es opcional? . En lugar de forzar el desenvolvimiento, urlEncoded!
puedes usar urlEncoded ?? ""
o if let urlEncoded = urlEncoded { ... }
.
Rápido 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