Objective-C y codificación Swift URL


137

Tengo un NSStringcomo este:

http://www.

pero quiero transformarlo a:

http%3A%2F%2Fwww.

¿Cómo puedo hacer esto?


1
Tengo una cadena encriptada como ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~: ¡ninguna de las soluciones a continuación parece abordar esto!
Mahendra Liya

Respuestas:


324

Para escapar de los personajes que quieres es un poco más de trabajo.

Código de ejemplo

iOS7 y superior:

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

Salida NSLog:

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

Los siguientes son útiles conjuntos de caracteres de codificación de URL:

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

Crear un conjunto de caracteres que combine todo lo anterior:

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

Creando una Base64

En el caso del juego de caracteres Base64:

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

Para Swift 3.0:

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

Para Swift 2.x:

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

Nota: stringByAddingPercentEncodingWithAllowedCharacterstambién codificará caracteres UTF-8 que necesitan codificación.

Pre iOS7 use Core Foundation con
Core Foundation con ARC:

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

Usando Core Foundation sin ARC:

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

Nota: -stringByAddingPercentEscapesUsingEncodingno producirá la codificación correcta, en este caso no codificará nada que devuelva la misma cadena.

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding codifica 14 caracteres:

`#% ^ {} [] | \" <> más el carácter de espacio como porcentaje escapado.

testString:

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

encodedString:

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

Nota: considere si este conjunto de caracteres satisface sus necesidades, si no, cámbielos según sea necesario.

RFC 3986 caracteres que requieren codificación (% agregado ya que es el prefijo de codificación):

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

Algunos "caracteres no reservados" están codificados adicionalmente:

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


1
También tenga en cuenta que puede usar el -stringByAddingPercentEscapesUsingEncodingmétodo de NSString .
Mike Weller

2
Ah sí, ahora recuerdo el stringByAddingPercentEscapesUsingEncodingcomportamiento funky . Solo codifica '&' y '=' o algo ridículo como ese.
Mike Weller

2
De acuerdo con RFC1738, también necesitaría codificar caracteres adicionales. Entonces, aunque esto responde a la pregunta del OP, tiene una utilidad limitada como codificador de URL de propósito general. Por ejemplo, no maneja no alfanuméricos como una diéresis alemana.
Alex Nauda

3
Esto no funciona (para la parte de iOS 7). Esto no convierte y en% 26.
coolcool1994

1
Crea el conjunto de caracteres que necesitas de un NSStringwith characterSetWithCharactersInString, toma el inverso con invertedSety úsalo con stringByAddingPercentEncodingWithAllowedCharacters. Para ver un ejemplo, vea esta respuesta SO .
zaph

22

Se llama codificación URL . Más aquí .

-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
           (CFStringRef)self,
           NULL,
           (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
           CFStringConvertNSStringEncodingToEncoding(encoding));
}

3
Esto sería mucho más útil si algún contenido de los enlaces que publicaste se incluyera en la respuesta.
Chown

1
CFURLCreateStringByAddingPercentEscapes()es obsoleto. Usar en su [NSString stringByAddingPercentEncodingWithAllowedCharacters:]lugar.
Pang

7

Esta no es mi solución. Alguien más escribió en stackoverflow pero he olvidado cómo.

De alguna manera, esta solución funciona "bien". Maneja caracteres diacríticos, chinos y casi cualquier otra cosa.

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

Si alguien me dijera quién escribió este código, realmente lo agradecería. Básicamente tiene alguna explicación de por qué esta cadena codificada se decodificará exactamente como lo desee.

Modifiqué un poco su solución. Me gusta que el espacio se represente con% 20 en lugar de +. Eso es todo.



¿Qué es [self UTF8String]?
Yuchao Zhou

1
@yuchaozh esta es una función que pones dentro de una categoría de NSString. Entonces, self es NSStirng y [self UTF8String] devuelve, asumiendo, su cadena en 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]];

1
liberar encodedString y url. Este código trata sobre el parámetro de codificación. Para codificar la cadena de paso de dirección completa en lugar de "parámetro".
Zahi

Esto funcionó para mí ... codificó incluso el carácter & con el que estaba teniendo problemas.
Виктор Иванов

3

Esto puede funcionar en Objective C ARC. Utilice CFBridgingRelease para emitir un objeto de estilo Core Foundation como un objeto Objective-C y transfiera la propiedad del objeto a ARC . Vea la función CFBridgingRelease aquí.

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

2

Swift iOS:

Solo para información: he usado esto:

extension String {

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

}// end extension String

1
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                             NULL,
                             (CFStringRef)yourString, 
                             NULL, 
                             CFSTR("/:"), 
                             kCFStringEncodingUTF8);

Deberá liberar o liberar automáticamente strusted mismo.


1

Esto es lo que uso. Tenga en cuenta que debe usar la @autoreleasepoolfunción o el programa podría bloquearse o bloquear el IDE. Tuve que reiniciar mi IDE tres veces hasta que me di cuenta de la solución. Parece que este código es compatible con ARC.

Esta pregunta se ha hecho muchas veces y se han dado muchas respuestas, pero lamentablemente todas las seleccionadas (y algunas otras sugeridas) están equivocadas.

Aquí está la cadena de prueba que usé: This is my 123+ test & test2. Got it?!

Estos son mis métodos de clase 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;
    }
}

0

Google implementa esto en su Google Toolbox para Mac . Así que es un buen lugar para conocer cómo lo están haciendo. Otra opción es incluir Toolbox y usar su implementación.

Verifique la implementación aquí . (Lo que se reduce exactamente a lo que la gente ha estado publicando aquí).


0

Así es como estoy haciendo esto rápidamente.

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

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

-1

// usa el método de instancia NSString de esta manera:

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

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

recuerde, solo debe codificar o decodificar el valor de su parámetro, no toda la url que solicita.


2
stringByReplacingPercentEscapeusingencoding: solo escapa & and = :-(
Sébastien Stormacq

1
Correcto, por lo que cosas como + no están codificadas, cuando es necesario. Así que no use la respuesta anterior
John Ballinger el

-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 );
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.