Codifica Objective-C e Swift URL


137

Ho un NSStringsimile:

http://www.

ma voglio trasformarlo in:

http%3A%2F%2Fwww.

Come posso fare questo?


1
Ho una stringa crittografata come ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~- nessuna delle soluzioni di seguito sembra risolverla!
Mahendra Liya,

Risposte:


324

Per sfuggire ai personaggi che vuoi è un po 'più di lavoro.

Codice di esempio

iOS7 e versioni successive:

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

Uscita NSLog:

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

Di seguito sono riportati utili set di caratteri di codifica URL:

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

Creazione di un set di caratteri che combina tutto quanto sopra:

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

Creazione di una Base64

Nel caso del set di caratteri Base64:

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

Per Swift 3.0:

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

Per Swift 2.x:

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

Nota: stringByAddingPercentEncodingWithAllowedCharacterscodificherà anche i caratteri UTF-8 che richiedono la codifica.

Pre iOS7 utilizza Core Foundation
utilizzando Core Foundation con ARC:

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

Utilizzo di Core Foundation senza ARC:

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

Nota: -stringByAddingPercentEscapesUsingEncodingnon produrrà la codifica corretta, in questo caso non codificherà nulla restituendo la stessa stringa.

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding codifica 14 caratteri:

`#% ^ {} [] | \" <> più il carattere spazio come percentuale di escape.

testString:

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

encodedString:

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

Nota: considera se questo set di personaggi soddisfa le tue esigenze, se non cambiarle secondo necessità.

Caratteri RFC 3986 che richiedono codifica (% aggiunta poiché è il prefisso di codifica):

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

Alcuni "caratteri senza prenotazione" sono inoltre codificati:

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


1
Si noti inoltre che è possibile utilizzare il -stringByAddingPercentEscapesUsingEncodingmetodo NSString .
Mike Weller,

2
Ah sì, ora ricordo il stringByAddingPercentEscapesUsingEncodingcomportamento funky . Codifica solo '&' e '=' o qualcosa di ridicolo come quello.
Mike Weller,

2
Secondo RFC1738 dovresti codificare anche caratteri aggiuntivi. Pertanto, sebbene ciò risponda alla domanda del PO, ha un'utilità limitata come codificatore URL generico. Ad esempio, non gestisce non alfanumerici come un umlaut tedesco.
Alex Nauda,

3
Questo non funziona (per la parte iOS 7). Questo non viene convertito e in% 26.
coolcool1994,

1
Crea il set di caratteri che ti serve da un NSStringcon characterSetWithCharactersInString, prendi l'inverso con invertedSete usalo con stringByAddingPercentEncodingWithAllowedCharacters. Per un esempio vedere questa risposta SO .
zaph,

22

Si chiama codifica URL . Più qui .

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

3
Ciò sarebbe molto più utile se alcuni contenuti dei link che hai pubblicato fossero inclusi nella risposta.
vestito l'

1
CFURLCreateStringByAddingPercentEscapes()è deprecato. Usa [NSString stringByAddingPercentEncodingWithAllowedCharacters:]invece.
Pang

7

Questa non è la mia soluzione. Qualcun altro ha scritto in StackOverflow ma ho dimenticato come.

In qualche modo questa soluzione funziona "bene". Gestisce i caratteri diacritici, cinesi e praticamente qualsiasi altra 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;
}

Se qualcuno mi dicesse chi ha scritto questo codice, lo apprezzerei davvero. Fondamentalmente ha qualche spiegazione sul perché questa stringa codificata decodificherà esattamente come desidera.

Ho modificato un po 'la sua soluzione. Mi piace che lo spazio sia rappresentato con% 20 anziché +. È tutto.



che cos'è [self UTF8String]?
Yuchao Zhou,

1
@yuchaozh questa è una funzione che hai inserito in una categoria di NSString. Quindi, self è NSStirng e [self UTF8String] restituisce, presumibilmente, la sua stringa in 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
rilasciare encodedString e url. questo codice riguarda il parametro encode. Per codificare l'intero indirizzo, passare la stringa anziché "parametro".
Zahi,

Questo ha funzionato per me ... ha codificato anche il carattere & con cui avevo problemi.
Виктор Иванов

3

Questo può funzionare in Objective C ARC.Usare CFBridgingRelease per lanciare un oggetto in stile Core Foundation come oggetto Objective-C e trasferire la proprietà dell'oggetto in ARC . Vedere Funzione CFBridgingRelease qui.

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

2

Swift iOS:

Solo per informazione: ho usato questo:

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

Dovrai rilasciare o rilasciare automaticamente strte stesso.


1

Ecco cosa uso. Nota che devi usare la @autoreleasepoolfunzione o il programma potrebbe bloccarsi o bloccare l'IDE. Ho dovuto riavviare il mio IDE tre volte fino a quando ho realizzato la correzione. Sembra che questo codice sia conforme ARC.

Questa domanda è stata posta molte volte e sono state fornite molte risposte, ma purtroppo tutte quelle selezionate (e alcune altre suggerite) sono sbagliate.

Ecco la stringa di test che ho usato: This is my 123+ test & test2. Got it?!

Questi sono i miei metodi di 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;
    }
}

0

Google lo implementa nella sua Google Toolbox per Mac . Quindi è un buon posto per raggiungere il picco su come lo stanno facendo. Un'altra opzione è quella di includere la Casella degli strumenti e utilizzare la loro implementazione.

Controlla l'implementazione qui . (Il che si riduce esattamente a ciò che le persone hanno pubblicato qui).


0

Questo è come lo sto facendo rapidamente.

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

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

-1

// usa il metodo dell'istanza NSString in questo modo:

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

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

ricorda, dovresti solo codificare o decodificare il valore del tuo parametro, non tutto l'URL richiesto.


2
stringByReplacingPercentEscapeusingencoding: scappa solo e e = :-(
Sébastien Stormacq

1
Corretto, quindi cose come + non sono codificate, quando devono essere. Quindi non usare la risposta sopra
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 );
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.