Substituição de stringByAddingPercentEscapesUsingEncoding no ios9?

112

No iOS8 e anteriores, posso usar:

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

no iOS9 stringByAddingPercentEscapesUsingEncodingfoi substituído por stringByAddingPercentEncodingWithAllowedCharacters:

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

e minha pergunta é: onde encontrar necessário NSCharacterSet( NSUTF8StringEncoding) para a substituição adequada de stringByAddingPercentEscapesUsingEncoding?

Slavik
fonte

Respostas:

131

A mensagem de suspensão de uso diz (ênfase minha):

Use stringByAddingPercentEncodingWithAllowedCharacters (_ :) em vez disso, que sempre usa a codificação UTF-8 recomendada e que codifica para um componente ou subcomponente de URL específico, uma vez que cada componente ou subcomponente de URL tem regras diferentes para quais caracteres são válidos.

Portanto, você só precisa fornecer um NSCharacterSetargumento adequado . Felizmente, para URLs, há um método de classe muito útil chamado URLHostAllowedCharacterSetque você pode usar assim:

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

Atualização para Swift 3 - o método se torna a propriedade estática urlHostAllowed:

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

Esteja ciente, porém, que:

Este método destina-se a codificar por cento um componente de URL ou string de subcomponente, NÃO uma string de URL inteira.

Antonio Favata
fonte
6
Além disso, eu sugiro fortemente o uso de NSURLComponents, que pode lidar com codificação de porcentagem para você.
Antonio Favata,
1
Alguma sugestão sobre o que usar para toda a string do URL?
Skill M2 de
1
@ SkillM2 Eu acho NSURLComponents(com cada componente codificado por cento com o correspondente NSCharacterSet) é o caminho certo a seguir.
Antonio Favata
2
Você nunca deve tentar codificar uma string de URL inteira. Isso pode causar bugs inesperados e, em alguns casos, falhas de segurança. A única maneira correta garantida de codificar um URL é fazer um pedaço de cada vez.
dgatwood
Ótimo. Muito obrigado, cara!
Felipe
100

Para Objective-C:

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

onde encontrar definido para NSUTF8StringEncoding?

Existem conjuntos de caracteres predefinidos para os seis componentes e subcomponentes de URL que permitem codificação percentual. Esses conjuntos de caracteres são passados ​​para -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

A mensagem de suspensão de uso diz (ênfase minha):

Use stringByAddingPercentEncodingWithAllowedCharacters (_ :) em vez disso, que sempre usa a codificação UTF-8 recomendada e que codifica para um componente ou subcomponente de URL específico, uma vez que cada componente ou subcomponente de URL tem regras diferentes para quais caracteres são válidos.

Portanto, você só precisa fornecer um NSCharacterSetargumento adequado . Felizmente, para URLs, há um método de classe muito útil chamado URLHostAllowedCharacterSetque você pode usar assim:

NSCharacterSet *set = [NSCharacterSet URLHostAllowedCharacterSet]; 

Esteja ciente, porém, que:

Este método destina-se a codificar por cento um componente de URL ou string de subcomponente, NÃO uma string de URL inteira.

ElonChan
fonte
4
Adoro quando a Apple torna a vida mais fácil. Obrigado, maçã.
Pato em
5
Qual é o significado de "Este método se destina a codificar por cento um componente de URL ou string de subcomponente, NÃO uma string de URL inteira." ?
GeneCode 01 de
4
URLHostAllowedCharacterSet estava apresentando o erro "URL não suportado", usei URLFragmentAllowedCharacterSet e está funcionando bem.
anoop4real
1
isto não funciona com + não irá codificá-lo e será substituído por espaço no lado do servidor conforme especificação.
Torge
45

URLHostAllowedCharacterSeté NÃO TRABALHAR PARA ME. Eu uso em URLFragmentAllowedCharacterSetvez disso.

OBJETIVO -C

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

SWIFT - 4

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

Os seguintes são conjuntos de caracteres úteis (invertidos):

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`
Lal Krishna
fonte
Obrigado e o mesmo para você também
Arpit B Parekh
Vale notar que nenhum desses conjuntos inclui +. Portanto, os sinais de mais na string serão bagunçados se passados ​​nos parâmetros de consulta - tratados como espaço `` no lado do servidor.
Asmo Soinio
21

Objective-C

este código funciona para mim:

urlString = [urlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
Bilal L
fonte
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;
}
}
Bobj-C
fonte
2

Para Swift 3.0

Você pode usar urlHostAllowedcharacterSet.

/// Retorna o conjunto de caracteres para caracteres permitidos em um subcomponente de URL de host.

public static var urlHostAllowed: CharacterSet { get }

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

Qual é o significado de "Este método destina-se a codificar por cento um componente de URL ou string de subcomponente, NÃO uma string de URL inteira." ? - GeneCode 01 de setembro de 16 às 8:30

Isso significa que você não deve codificar o https://xpto.example.com/path/subpathdo url, mas apenas o que vem depois do ?.

Suposto, porque há casos de uso para fazer isso em casos como:

https://example.com?redirectme=xxxxx

Onde xxxxxestá um URL totalmente codificado.

meio que
fonte
0

Adicionando à resposta aceita. Levando em consideração esta nota

Este método destina-se a codificar por cento um componente de URL ou string de subcomponente, NÃO uma string de URL inteira.

todo o URL não deve ser codificado:

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!
Ayman Ibrahim
fonte