Objective-C- und Swift-URL-Codierung

137

Ich habe NSStringso etwas:

http://www.

aber ich möchte es umwandeln in:

http%3A%2F%2Fwww.

Wie kann ich das machen?

Usi Usi
quelle
1
Ich habe eine verschlüsselte Zeichenfolge wie ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~- keine der folgenden Lösungen scheint dies zu beheben!
Mahendra Liya

Antworten:

324

Den gewünschten Charakteren zu entkommen, ist etwas mehr Arbeit.

Beispielcode

iOS7 und höher:

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

NSLog-Ausgabe:

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

Die folgenden nützlichen URL-Codierungszeichensätze sind:

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

Erstellen eines Zeichensatzes, der alle oben genannten Elemente kombiniert:

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

Erstellen einer Base64

Im Fall des Base64-Zeichensatzes:

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

Für Swift 3.0:

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

Für Swift 2.x:

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

Hinweis: stringByAddingPercentEncodingWithAllowedCharactersCodiert auch UTF-8-Zeichen, die codiert werden müssen.

Verwenden von Core Foundation vor iOS7
Verwenden von Core Foundation mit ARC:

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

Verwenden von Core Foundation ohne ARC:

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

Hinweis: Es -stringByAddingPercentEscapesUsingEncodingwird nicht die richtige Codierung erzeugt. In diesem Fall wird nichts codiert, das dieselbe Zeichenfolge zurückgibt.

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding codiert 14 Zeichen:

`#% ^ {} [] | \" <> plus das Leerzeichen in Prozent.

testString:

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

encodedString:

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

Hinweis: Überlegen Sie, ob dieser Zeichensatz Ihren Anforderungen entspricht, und ändern Sie ihn nicht nach Bedarf.

Zu codierende RFC 3986-Zeichen (% hinzugefügt, da es sich um das Codierungspräfixzeichen handelt):

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

Einige "nicht reservierte Zeichen" werden zusätzlich codiert:

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

zaph
quelle
1
Beachten Sie auch, dass Sie die -stringByAddingPercentEscapesUsingEncodingMethode von NSString verwenden können.
Mike Weller
2
Ah ja, jetzt erinnere ich mich an das funky stringByAddingPercentEscapesUsingEncodingVerhalten. Es codiert nur '&' und '=' oder so etwas Lächerliches.
Mike Weller
2
Laut RFC1738 müssten Sie auch zusätzliche Zeichen codieren. Obwohl dies die Frage des OP beantwortet, ist es als universeller URL-Encoder nur begrenzt nützlich. Zum Beispiel werden nicht alphanumerische Zeichen wie ein deutscher Umlaut nicht behandelt.
Alex Nauda
3
Dies funktioniert nicht (für iOS 7 Teil). Dies konvertiert & nicht in% 26.
coolcool1994
1
Erstellen Sie den Zeichensatz, den Sie benötigen, aus einem NSStringmit characterSetWithCharactersInString, nehmen Sie die Umkehrung mit invertedSetund verwenden Sie diesen mit stringByAddingPercentEncodingWithAllowedCharacters. Ein Beispiel finden Sie in dieser SO-Antwort .
Zaph
22

Es heißt URL-Codierung . Mehr hier .

-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
           (CFStringRef)self,
           NULL,
           (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
           CFStringConvertNSStringEncodingToEncoding(encoding));
}
Larsacus
quelle
3
Dies wäre viel nützlicher, wenn einige Inhalte der von Ihnen geposteten Links in die Antwort aufgenommen würden.
Chown
1
CFURLCreateStringByAddingPercentEscapes()ist veraltet. Verwenden Sie [NSString stringByAddingPercentEncodingWithAllowedCharacters:]stattdessen.
Pang
7

Das ist nicht meine Lösung. Jemand anderes hat in stackoverflow geschrieben, aber ich habe vergessen wie.

Irgendwie funktioniert diese Lösung "gut". Es behandelt diakritische, chinesische Zeichen und so ziemlich alles andere.

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

Wenn mir jemand sagen würde, wer diesen Code geschrieben hat, würde ich ihn wirklich schätzen. Grundsätzlich hat er eine Erklärung, warum diese codierte Zeichenfolge genau so decodiert, wie sie es wünscht.

Ich habe seine Lösung ein wenig modifiziert. Ich möchte, dass Leerzeichen mit% 20 und nicht mit + dargestellt werden. Das ist alles.

Anonymes Weiß
quelle
Was ist [selbst UTF8String]?
Yuchao Zhou
1
@yuchaozh Dies ist eine Funktion, die Sie in eine Kategorie von NSString einfügen. Self ist also NSStirng und [self UTF8String] gibt vermutlich seine Zeichenfolge im UTF8-Format zurück.
Kelsey
4
 NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );

NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];
Zahi
quelle
1
Geben Sie encodedString und url frei. In diesem Code geht es um Codierungsparameter. Um die gesamte Adresse zu codieren, übergeben Sie eine Zeichenfolge anstelle von "Parameter".
Zahi
Dies funktionierte für mich ... verschlüsselte sogar den & Charakter, mit dem ich Probleme hatte.
Виктор Иванов
3

Dies kann in Objective C ARC funktionieren. Verwenden Sie CFBridgingRelease, um ein Objekt im Core Foundation-Stil als Objective-C-Objekt umzuwandeln und das Eigentum an dem Objekt auf ARC zu übertragen . Siehe Funktion CFBridgingRelease hier.

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

Schnelles iOS:

Nur zur Information: Ich habe dies verwendet:

extension String {

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

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

Sie müssen sich freigeben oder automatisch freigeben str.

Wevah
quelle
1

Folgendes benutze ich. Beachten Sie, dass Sie die @autoreleasepoolFunktion verwenden müssen, da das Programm sonst abstürzen oder die IDE blockieren kann. Ich musste meine IDE dreimal neu starten, bis ich das Update erkannte. Es scheint, dass dieser Code ARC-kompatibel ist.

Diese Frage wurde oft gestellt und viele Antworten gegeben, aber leider sind alle ausgewählten (und einige andere vorgeschlagenen) falsch.

Hier ist die Testzeichenfolge, die ich verwendet habe: This is my 123+ test & test2. Got it?!

Dies sind meine Objective C ++ - Klassenmethoden:

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
quelle
0

Google implementiert dies in seiner Google Toolbox für Mac . Das ist also ein guter Ort, um zu zeigen, wie sie es machen. Eine weitere Option besteht darin, die Toolbox einzuschließen und ihre Implementierung zu verwenden.

Überprüfen Sie die Implementierung hier . (Was genau darauf ankommt, was die Leute hier gepostet haben).

wrtsprt
quelle
0

So mache ich das schnell.

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

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

// Verwenden Sie die NSString-Instanzmethode wie folgt:

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

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

Denken Sie daran, dass Sie nur für Ihren Parameterwert codieren oder decodieren sollten, nicht für alle von Ihnen angeforderten URLs.

Lingtianlan
quelle
2
stringByReplacingPercentEscapeusingencoding: entkommt nur & und = :-(
Sébastien Stormacq
1
Richtig, also werden Dinge wie + nicht codiert, wenn es sein muss. Verwenden Sie also nicht die obige Antwort
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
quelle