Cómo codificar una URL en Swift

Esta es mi URL

El problema es que el campo de address no se anexa a urlpath .

¿Alguien sabe por qué es eso?

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

Utilice stringByAddingPercentEncodingWithAllowedCharacters :

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

Utilice stringByAddingPercentEscapesUsingEncoding: Obsoleto en iOS 9 y 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)") 

Si es posible que el valor que está agregando a su URL pueda tener caracteres reservados (como se define en la sección 2 de RFC 3986 ), es posible que deba refinar su porcentaje de escape. Notablemente, mientras que & y + son caracteres válidos en una URL, no son válidos dentro de un valor de parámetro de consulta de URL (porque & se usa como delimitador entre parámetros de consulta que terminarían prematuramente su valor, y + se traduce a un carácter de espacio) . Desafortunadamente, el porcentaje de escape estándar deja esos delimitadores sin escindir.

Por lo tanto, es posible que desee porcentaje de escape de todos los caracteres que no están dentro de la lista de caracteres sin reserva de RFC 3986:

Los caracteres que están permitidos en un URI pero no tienen un propósito reservado se llaman sin reservas. Estos incluyen letras mayúsculas y minúsculas, dígitos decimales, guiones, punto, guión bajo y tilde.

      sin reserva = ALPHA / DIGIT / "-" / "."  / "_" / "~"

Más tarde, en la sección 3.4, el RFC además contempla agregar ? y / a la lista de caracteres permitidos dentro de una consulta:

Los caracteres barra (“/”) y signo de interrogación (“?”) Pueden representar datos dentro del componente de consulta. Tenga en cuenta que algunas implementaciones más antiguas y erróneas pueden no manejar dichos datos correctamente cuando se utiliza como el URI base para referencias relativas (Sección 5.1), aparentemente porque no pueden distinguir los datos de consulta de los datos de ruta al buscar separadores jerárquicos. Sin embargo, como los componentes de consulta se usan a menudo para transportar información de identificación en forma de pares “clave = valor” y un valor frecuentemente utilizado es una referencia a otro URI, a veces es mejor para la usabilidad evitar el porcentaje de encoding de esos caracteres.

Hoy en día, generalmente URLComponents para escapar por ciento del valor de la consulta:

 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! 

Por cierto, aunque no está contemplado en el RFC mencionado anteriormente, la sección 4.10.22.6, datos de formulario codificados en URL , de la especificación HTML W3C dice que las application/x-www-form-urlencoded también deben reemplazar caracteres espaciales con + caracteres ( e incluye el asterisco en los caracteres que no deberían escaparse). Y, desafortunadamente, URLComponents no escapará adecuadamente por ciento de esto, por lo que Apple aconseja que usted por ciento lo escape manualmente antes de recuperar la propiedad url del objeto URLComponents :

 // configure `components` as shown above, and then: components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B") let url = components.url! 

Para Swift 2 rendition, donde manualmente hago todo este porcentaje escapándome, vea la revisión anterior de esta respuesta .

Swift 3:

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

Swift 2.0

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

Consejos y trucos útiles de progtwigción

URLQueryAllowedCharacterSet no se debe utilizar para la encoding URL de los parámetros de consulta porque este juego de caracteres incluye & URLQueryAllowedCharacterSet , / etc. que sirven como delimitadores en una consulta de URL, por ejemplo

 /?paramname=paramvalue&paramname=paramvalue 

Estos caracteres están permitidos en consultas de URL como un todo, pero no en valores de parámetros.

RFC 3986 habla específicamente de caracteres no reservados , que son diferentes de los permitidos:

2.3. Personajes sin reserva

Caracteres que están permitidos en un URI pero no tienen una reserva
propósito se llaman sin reservas. Estos incluyen letras mayúsculas y minúsculas, dígitos decimales, guiones, punto, guión bajo y tilde.

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

En consecuencia:

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

El código anterior no hace una llamada a alphanumericCharacterSet debido al enorme tamaño del juego de caracteres que devuelve (103806 caracteres). Y a la vista de la cantidad de caracteres Unicode que permite alphanumericCharacterSet , utilizarlo con el propósito de la encoding de URL sería simplemente erróneo.

Uso:

 let URLEncodedString = myString.URLEncoded 

XCODE 8, SWIFT 3.0

De grokswift

Crear URL a partir de cadenas es un campo minado para los errores. ¿Solo perder una sola / o accidentalmente URL codificar? en una consulta y su llamada API fallará y su aplicación no tendrá ningún dato para mostrar (o incluso se bloqueará si no previó esa posibilidad). Desde iOS 8, existe una mejor forma de crear URL utilizando NSURLComponents y 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 } 

A continuación se muestra el código para acceder a la url usando la statement de guard .

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

Salida:

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

Leer más: creación de URL con NSURLComponents y NSURLQueryItems

Actualizado para Swift 3:

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

Swift 4.1

Cree un “Conjunto de caracteres” según la opción que desee (urlQueryAllowed). A continuación, elimine los caracteres adicionales que no desea (+ y). Luego pase ese conjunto de caracteres a “addingPercentEncoding”.

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

En Mac OS 10.9 se ha introducido Maverics y iOS 7 NSURLComponents que maneja la encoding de las diferentes partes de la URL de una manera bastante conveniente.

La clase NSURLComponents es una clase que está diseñada para analizar URL basadas en RFC 3986 y para construir URL a partir de sus partes constituyentes. Su comportamiento difiere sutilmente de la clase NSURL, que se ajusta a las RFC más antiguas. Sin embargo, puede obtener fácilmente un objeto NSURL basado en los contenidos de un objeto de componentes URL o viceversa.

 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) 

Simplemente completando la respuesta de Desmond Hume para extender la clase String para una función de encoding válida de caracteres sin reserva RFC 3986 (necesaria si está codificando parámetros de FORMULACIÓN de consulta):

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

Necesitaba codificar mis parámetros con ISO-8859-1, por lo que el método addingPercentEncoding () no funciona para mí. Hice mi propia solución en Swift 4:

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

Uso:

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

En mi caso, donde el último componente era caracteres no latinos, hice lo siguiente en Swift 2.2 :

 extension String { func encodeUTF8() -> String? { //If I can create an NSURL out of the string nothing is wrong with it if let _ = NSURL(string: self) { return self } //Get the last component from the string this will return subSequence let optionalLastComponent = self.characters.split { $0 == "/" }.last if let lastComponent = optionalLastComponent { //Get the string from the sub sequence by mapping the characters to [String] then reduce the array to String let lastComponentAsString = lastComponent.map { String($0) }.reduce("", combine: +) //Get the range of the last component if let rangeOfLastComponent = self.rangeOfString(lastComponentAsString) { //Get the string without its last component let stringWithoutLastComponent = self.substringToIndex(rangeOfLastComponent.startIndex) //Encode the last component if let lastComponentEncoded = lastComponentAsString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.alphanumericCharacterSet()) { //Finally append the original string (without its last component) to the encoded part (encoded last component) let encodedString = stringWithoutLastComponent + lastComponentEncoded //Return the string (original string/encoded string) return encodedString } } } return nil; } } 

Añadiendo a la respuesta de Bryan Chen arriba:

Solo en caso de que alguien más esté obteniendo algo similar con Alamofire:

error: Alamofire se compiló con optimización; el paso puede tener un comportamiento extraño; las variables pueden no estar disponibles.

No es un error muy descriptivo. Estaba obteniendo ese error al construir una URL para google geo services. Estaba agregando una dirección al final de la URL SIN codificar primero la dirección de la calle. Pude arreglarlo usando la solución de Bryan Chen:

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

¡Eso lo solucionó! No me gustó que la dirección tuviera espacios y comas, etc.

¡Espero que esto ayude a alguien más!