Codificação de URL Objective-C e Swift

137

Eu tenho um NSStringassim:

http://www.

mas quero transformá-lo para:

http%3A%2F%2Fwww.

Como posso fazer isso?

Usi Usi
fonte
1
Eu tenho uma string criptografada como ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~- nenhuma das soluções abaixo parece resolver isso!
Mahendra Liya

Respostas:

324

Escapar dos personagens que você quer é um pouco mais de trabalho.

Código de exemplo

iOS7 e superior:

NSString *unescaped = @"http://www";
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(@"escapedString: %@", escapedString);

Saída NSLog:

escapedString: http% 3A% 2F% 2Fwww

A seguir, são úteis conjuntos de caracteres de codificação de URL:

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

Criando um conjunto de caracteres combinando todos os itens acima:

NSCharacterSet *URLCombinedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>?@[\\]^`{|}"] invertedSet];

Criando um Base64

No caso do conjunto de caracteres Base64:

NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet];

Para o Swift 3.0:

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)

Para Swift 2.x:

var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())

Nota: stringByAddingPercentEncodingWithAllowedCharacterstambém codificará caracteres UTF-8 que precisam de codificação.

Antes do iOS7, use o Core Foundation
usando o Core Foundation With ARC:

NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
    NULL,
   (__bridge CFStringRef) unescaped,
    NULL,
    CFSTR("!*'();:@&=+$,/?%#[]\" "),
    kCFStringEncodingUTF8));

Usando o Core Foundation Without ARC:

NSString *escapedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
    NULL,
   (CFStringRef)unescaped,
    NULL,
    CFSTR("!*'();:@&=+$,/?%#[]\" "),
    kCFStringEncodingUTF8);

Nota: -stringByAddingPercentEscapesUsingEncodingnão produzirá a codificação correta; nesse caso, não codificará nada que retorne a mesma string.

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding codifica 14 caracteres:

`#% ^ {} [] | \" <> mais o caractere de espaço como porcentagem de escape.

testString:

" `~!@#$%^&*()_+-={}[]|\\:;\"'<,>.?/AZaz"  

encodedString:

"%20%60~!@%23$%25%5E&*()_+-=%7B%7D%5B%5D%7C%5C:;%22'%3C,%3E.?/AZaz"  

Nota: considere se esse conjunto de caracteres atende às suas necessidades; caso contrário, altere-os conforme necessário.

Caracteres RFC 3986 que exigem codificação (% adicionado, pois é o caractere de prefixo de codificação):

"! # $ & '() * +, /:; =? @ []%"

Alguns "caracteres não reservados" também são codificados:

"\ n \ r \"% -. <> \ ^ _ `{|} ~"

zaph
fonte
1
Observe também que você pode usar o -stringByAddingPercentEscapesUsingEncodingmétodo NSString .
Mike Weller
2
Ah sim, agora me lembro do stringByAddingPercentEscapesUsingEncodingcomportamento descolado . Ele codifica apenas '&' e '=' ou algo ridículo assim.
Mike Weller
2
De acordo com o RFC1738, você também precisará codificar caracteres adicionais. Portanto, embora isso responda à pergunta do OP, ele tem utilidade limitada como codificador de URL de uso geral. Por exemplo, ele não lida com dados não alfanuméricos, como um trema alemão.
Alex Nauda
3
Isso não funciona (na parte do iOS 7). Isso não converte & em% 26.
precisa
1
Crie o conjunto de caracteres que você precisa de NSStringcom characterSetWithCharactersInString, leve o inverso com invertedSete use-o com stringByAddingPercentEncodingWithAllowedCharacters. Para um exemplo, veja esta resposta SO .
Zaph
22

É chamado de codificação de URL . Mais aqui .

-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
           (CFStringRef)self,
           NULL,
           (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
           CFStringConvertNSStringEncodingToEncoding(encoding));
}
Larsacus
fonte
3
Isso seria muito mais útil se algum conteúdo dos links que você publicou fosse incluído na resposta.
Chown
1
CFURLCreateStringByAddingPercentEscapes()está obsoleto. Use em [NSString stringByAddingPercentEncodingWithAllowedCharacters:]vez disso.
Pang
7

Esta não é a minha solução. Alguém escreveu no stackoverflow, mas eu esqueci como.

De alguma forma, essa solução funciona "bem". Ele lida com caracteres diacríticos, chineses e praticamente qualquer outra coisa.

- (NSString *) URLEncodedString {
    NSMutableString * output = [NSMutableString string];
    const char * source = [self UTF8String];
    int sourceLen = strlen(source);
    for (int i = 0; i < sourceLen; ++i) {
        const unsigned char thisChar = (const unsigned char)source[i];
        if (false && thisChar == ' '){
            [output appendString:@"+"];
        } else if (thisChar == '.' || thisChar == '-' || thisChar == '_' || thisChar == '~' ||
                   (thisChar >= 'a' && thisChar <= 'z') ||
                   (thisChar >= 'A' && thisChar <= 'Z') ||
                   (thisChar >= '0' && thisChar <= '9')) {
            [output appendFormat:@"%c", thisChar];
        } else {
            [output appendFormat:@"%%%02X", thisChar];
        }
    }
    return output;
}

Se alguém me disser quem escreveu esse código, eu realmente aprecio isso. Basicamente, ele tem algumas explicações sobre por que essa string codificada decodifica exatamente como deseja.

Eu modifiquei um pouco a solução dele. Eu gosto de espaço a ser representado com% 20 em vez de +. Isso é tudo.

Branco anônimo
fonte
o que é [self UTF8String]?
Yuchao Zhou
1
@ yuchaozh essa é uma função que você coloca dentro de uma categoria de NSString. Portanto, self é NSStirng e [self UTF8String] retorna, supostamente, sua string no formato UTF8.
Kelsey
4
 NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );

NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];
Zahi
fonte
1
libere encodedString e url. esse código é sobre parâmetro de codificação. Para codificar o endereço inteiro, passe a sequência em vez de "parâmetro".
Zahi
Isso funcionou para mim ... codificou até o personagem & com o qual eu estava tendo problemas.
214153Data do upload
3

Isso pode funcionar no ARC do Objetivo C.Use CFBridgingRelease para converter um objeto no estilo Core Foundation como um objeto Objective-C e transferir a propriedade do objeto para o ARC. Consulte a Função CFBridgingRelease aqui.

+ (NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes
                         (kCFAllocatorDefault,
                          (__bridge CFStringRef)string,
                          NULL,
                          CFSTR("!*'();:@&=+$,/?%#[]"),
                          kCFStringEncodingUTF8)
                         );}
Neuneed
fonte
2

IOS rápido:

Apenas para informação: Eu usei isso:

extension String {

    func urlEncode() -> CFString {
        return CFURLCreateStringByAddingPercentEscapes(
            nil,
            self,
            nil,
            "!*'();:@&=+$,/?%#[]",
            CFStringBuiltInEncodings.UTF8.rawValue
        )
    }

}// end extension String
Vinod Joshi
fonte
1
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                             NULL,
                             (CFStringRef)yourString, 
                             NULL, 
                             CFSTR("/:"), 
                             kCFStringEncodingUTF8);

Você precisará liberar ou autorelease strvocê mesmo.

Wevah
fonte
1

Aqui está o que eu uso. Observe que você precisa usar o@autoreleasepool recurso ou o programa pode travar ou bloquear o IDE. Eu tive que reiniciar meu IDE três vezes até perceber a correção. Parece que este código é compatível com ARC.

Esta pergunta já foi feita muitas vezes, e muitas respostas foram dadas, mas infelizmente todas as selecionadas (e algumas sugeridas) estão erradas.

Aqui está a sequência de teste que eu usei: This is my 123+ test & test2. Got it?!

Estes são meus métodos de classe Objective C ++:

static NSString * urlDecode(NSString *stringToDecode) {
    NSString *result = [stringToDecode stringByReplacingOccurrencesOfString:@"+" withString:@" "];
    result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    return result;
}

static NSString * urlEncode(NSString *stringToEncode) {
    @autoreleasepool {
        NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
                NULL,
                (CFStringRef)stringToEncode,
                NULL,
                (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
                kCFStringEncodingUTF8
            ));
        result = [result stringByReplacingOccurrencesOfString:@"%20" withString:@"+"];
        return result;
    }
}
Volomike
fonte
0

O Google implementa isso na Google Toolbox for Mac . Portanto, esse é um bom lugar para saber como eles estão fazendo isso. Outra opção é incluir a caixa de ferramentas e usar sua implementação.

Confira a implementação aqui . (Que se resume exatamente ao que as pessoas estão postando aqui).

wrtsprt
fonte
0

É assim que estou fazendo isso rapidamente.

extension String {
    func encodeURIComponent() -> String {
        return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
    }

    func decodeURIComponent() -> String {
        return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
    }
}
Andy
fonte
-1

// use o método de instância NSString assim:

+ (NSString *)encodeURIComponent:(NSString *)string
{
NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}

+ (NSString *)decodeURIComponent:(NSString *)string
{
NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}

lembre-se, você deve codificar ou decodificar apenas o valor do parâmetro, e não todo o URL solicitado.

lingtianlan
fonte
2
stringByReplacingPercentEscapeusingencoding: apenas escapa & e = :-(
Sébastien Stormacq
1
Correto, para que coisas como + não sejam codificadas, quando precisam ser. Portanto, não use a resposta acima
John Ballinger
-8
int strLength = 0;
NSString *urlStr = @"http://www";
NSLog(@" urlStr : %@", urlStr );
NSMutableString *mutableUrlStr = [urlStr mutableCopy];
NSLog(@" mutableUrlStr : %@", mutableUrlStr );
strLength = [mutableUrlStr length];
[mutableUrlStr replaceOccurrencesOfString:@":" withString:@"%3A" options:NSCaseInsensitiveSearch range:NSMakeRange(0, strLength)];
NSLog(@" mutableUrlStr : %@", mutableUrlStr );
strLength = [mutableUrlStr length];
[mutableUrlStr replaceOccurrencesOfString:@"/" withString:@"%2F" options:NSCaseInsensitiveSearch range:NSMakeRange(0, strLength)];
NSLog(@" mutableUrlStr : %@", mutableUrlStr );
ader
fonte