¿Reemplazo de stringByAddingPercentEscapesUsingEncoding en ios9?


112

En iOS8 y anteriores puedo usar:

NSString *str = ...; // some URL
NSString *result = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

en iOS9 stringByAddingPercentEscapesUsingEncodingha sido reemplazado por stringByAddingPercentEncodingWithAllowedCharacters:

NSString *str = ...; // some URL
NSCharacterSet *set = ???; // where to find set for NSUTF8StringEncoding?
NSString *result = [str stringByAddingPercentEncodingWithAllowedCharacters:set];

y mi pregunta es: ¿dónde encontrar necesario NSCharacterSet( NSUTF8StringEncoding) para el reemplazo adecuado de stringByAddingPercentEscapesUsingEncoding?

Respuestas:


131

El mensaje de desaprobación dice (el énfasis es mío):

En su lugar, use stringByAddingPercentEncodingWithAllowedCharacters (_ :), que siempre usa la codificación UTF-8 recomendada y que codifica para un componente o subcomponente de URL específico, ya que cada componente o subcomponente de URL tiene diferentes reglas sobre qué caracteres son válidos.

Por lo tanto, solo necesita proporcionar un NSCharacterSetargumento adecuado . Afortunadamente, para las URL hay un método de clase muy útil llamado URLHostAllowedCharacterSetque puede usar así:

let encodedHost = unencodedHost.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())

Actualización para Swift 3 : el método se convierte en la propiedad estática urlHostAllowed:

let encodedHost = unencodedHost.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

Sin embargo, tenga en cuenta que:

Este método está diseñado para codificar en porcentaje un componente de URL o una cadena de subcomponentes, NO una cadena de URL completa.


6
Además, sugiero encarecidamente usar NSURLComponents, que puede manejar la codificación porcentual por usted.
Antonio Favata

1
¿Alguna sugerencia sobre qué usar para toda la cadena de URL?
Habilidad M2

1
@ SkillM2 Creo que NSURLComponents(con cada componente codificado en porcentaje con el correspondiente NSCharacterSet) es el camino correcto a seguir.
Antonio Favata

2
Nunca, nunca, nunca intente codificar una cadena de URL completa. Puede causar errores inesperados y, en algunos casos, agujeros de seguridad. La única forma correcta garantizada de codificar una URL es hacerlo una pieza a la vez.
dgatwood

Excelente. ¡Muchas gracias, amigo!
Felipe

100

Para Objective-C:

NSString *str = ...; // some URL
NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 
NSString *result = [str stringByAddingPercentEncodingWithAllowedCharacters:set];

¿Dónde encontrar el conjunto para NSUTF8StringEncoding?

Hay juegos de caracteres predefinidos para los seis componentes y subcomponentes de URL que permiten la codificación porcentual. Estos juegos de caracteres se pasan a -stringByAddingPercentEncodingWithAllowedCharacters:.

 // Predefined character sets for the six URL components and subcomponents which allow percent encoding. These character sets are passed to -stringByAddingPercentEncodingWithAllowedCharacters:.
@interface NSCharacterSet (NSURLUtilities)
+ (NSCharacterSet *)URLUserAllowedCharacterSet;
+ (NSCharacterSet *)URLPasswordAllowedCharacterSet;
+ (NSCharacterSet *)URLHostAllowedCharacterSet;
+ (NSCharacterSet *)URLPathAllowedCharacterSet;
+ (NSCharacterSet *)URLQueryAllowedCharacterSet;
+ (NSCharacterSet *)URLFragmentAllowedCharacterSet;
@end

El mensaje de desaprobación dice (el énfasis es mío):

En su lugar, use stringByAddingPercentEncodingWithAllowedCharacters (_ :), que siempre usa la codificación UTF-8 recomendada y que codifica para un componente o subcomponente de URL específico, ya que cada componente o subcomponente de URL tiene diferentes reglas sobre qué caracteres son válidos.

Por lo tanto, solo necesita proporcionar un NSCharacterSetargumento adecuado . Afortunadamente, para las URL hay un método de clase muy útil llamado URLHostAllowedCharacterSetque puede usar así:

NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 

Sin embargo, tenga en cuenta que:

Este método está diseñado para codificar en porcentaje un componente de URL o una cadena de subcomponentes, NO una cadena de URL completa.


4
Me encanta cuando Apple hace la vida más fácil. Gracias manzana.
Duck

5
Cuál es el significado de "Este método está diseñado para codificar porcentualmente un componente de URL o una cadena de subcomponentes, NO una cadena de URL completa". ?
GeneCode

4
URLHostAllowedCharacterSet estaba dando el error "URL no admitida", utilicé URLFragmentAllowedCharacterSet y funciona bien.
anoop4real

1
esto no funciona con + no lo codificará y será reemplazado por espacio en el lado del servidor como por especificación.
Torge

45

URLHostAllowedCharacterSetse NO TRABAJO PARA MÍ. Yo uso URLFragmentAllowedCharacterSeten su lugar.

C OBJETIVO

NSCharacterSet *set = [NSCharacterSet URLFragmentAllowedCharacterSet];
NSString * encodedString = [@"url string" stringByAddingPercentEncodingWithAllowedCharacters:set];

SWIFT - 4

"url string".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)

Los siguientes son conjuntos de caracteres útiles (invertidos):

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

Gracias y lo mismo para ti también
Arpit B Parekh

Vale la pena señalar que ninguno de estos conjuntos incluye +. Por lo tanto, los signos más en la cadena se estropearán si se pasan en los parámetros de consulta, se tratarán como espacio `` en el lado del servidor.
Asmo Soinio

21

C objetivo

este código funciona para mí:

urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];

4

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

2

Para Swift 3.0

Puede utilizar urlHostAllowedcharacterSet.

/// Devuelve el juego de caracteres para los caracteres permitidos en un subcomponente de URL de host.

public static var urlHostAllowed: CharacterSet { get }

WebserviceCalls.getParamValueStringForURLFromDictionary(settingsDict as! Dictionary<String, AnyObject>).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlHostAllowed)

1

Cuál es el significado de "Este método está destinado a codificar porcentualmente un componente de URL o una cadena de subcomponentes, NO una cadena de URL completa". ? - GeneCode 1 de septiembre de 2016 a las 8:30

Significa que no se supone que debe codificar el https://xpto.example.com/path/subpathde la URL, sino solo lo que va después del ?.

Supuestamente, porque hay casos de uso para hacerlo en casos como:

https://example.com?redirectme=xxxxx

¿Dónde xxxxxestá una URL totalmente codificada?


0

Añadiendo a la respuesta aceptada. Teniendo en cuenta esta nota

Este método está diseñado para codificar en porcentaje un componente de URL o una cadena de subcomponentes, NO una cadena de URL completa.

la URL completa no debe estar codificada:

let param = "=color:green|\(latitude),\(longitude)&\("zoom=13&size=\(width)x\(height)")&sensor=true&key=\(staticMapKey)".addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) 
let url = "https://maps.google.com/maps/api/staticmap?markers" + param!
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.