Frage Objective-c iPhone Prozent codieren eine Zeichenfolge?


Ich möchte die prozentcodierte Zeichenkette für diese spezifischen Buchstaben erhalten, wie geht das in objective-c?

Reserved characters after percent-encoding
!   *   '   (   )   ;   :   @   &   =   +   $   ,   /   ?   #   [   ]
%21 %2A %27 %28 %29 %3B %3A %40 %26 %3D %2B %24 %2C %2F %3F %23 %5B %5D

Prozentkodierung Wiki

Bitte testen Sie mit dieser Zeichenfolge und sehen Sie, ob es funktioniert:

myURL = @"someurl/somecontent"

Ich möchte, dass die Zeichenfolge wie folgt aussieht:

myEncodedURL = @"someurl%2Fsomecontent"

Ich habe es mit dem versucht stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding schon, aber es funktioniert nicht, das Ergebnis ist immer noch das gleiche wie die ursprüngliche Zeichenfolge. Bitte um Rat.


69
2017-08-06 12:02


Ursprung


Antworten:


Ich habe beides gefunden stringByAddingPercentEscapesUsingEncoding: und CFURLCreateStringByAddingPercentEscapes() sind unzureichend. Das NSString Methode vermisst einige Zeichen, und die CF-Funktion lässt Sie nur sagen, welche (spezifische) Zeichen Sie entkommen möchten. Die korrekte Spezifikation besteht darin, alle Zeichen außer einem kleinen Satz zu entkommen.

Um das zu beheben, habe ich ein NSString Kategoriemethode zum korrekten Codieren einer Zeichenfolge. Es wird in Prozent alles außer allem kodieren [a-zA-Z0-9.-_~] und wird auch Leerzeichen als codieren + (gemäß diese Spezifikation). Es wird auch korrekt Unicode-Zeichen codieren.

- (NSString *) URLEncodedString_ch {
    NSMutableString * output = [NSMutableString string];
    const unsigned char * source = (const unsigned char *)[self UTF8String];
    int sourceLen = strlen((const char *)source);
    for (int i = 0; i < sourceLen; ++i) {
        const unsigned char thisChar = source[i];
        if (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;
}

139
2017-08-06 17:20



Das iOS 7 SDK bietet jetzt eine bessere Alternative zustringByAddingPercentEscapesUsingEncoding Dadurch können Sie angeben, dass alle Zeichen außer bestimmten zulässigen Zeichen maskiert werden sollen. Es funktioniert gut, wenn Sie die URL in Teilen aufbauen:

NSString * unescapedQuery = [[NSString alloc] initWithFormat:@"?myparam=%d", numericParamValue];
NSString * escapedQuery = [unescapedQuery stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString * urlString = [[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext%@", escapedQuery];

Obwohl es weniger häufig ist, dass die anderen Teile der URL Variablen sind, gibt es auch Konstanten in der Kategorie NSURLUtilities für diese:

[NSCharacterSet URLHostAllowedCharacterSet]
[NSCharacterSet URLUserAllowedCharacterSet]
[NSCharacterSet URLPasswordAllowedCharacterSet]
[NSCharacterSet URLPathAllowedCharacterSet]
[NSCharacterSet URLFragmentAllowedCharacterSet]

[NSCharacterSet URLQueryAllowedCharacterSet] beinhaltet alle der Zeichen, die im Abfrageteil der URL zulässig sind (der Teil, der mit der URL beginnt ? und vor dem # für ein Fragment, wenn überhaupt) einschließlich der ? und das & oder = Zeichen, mit denen die Parameternamen und -werte abgegrenzt werden. Bei Abfrageparametern mit alphanumerischen Werten können diese Zeichen in den Werten der Variablen enthalten sein, die zum Erstellen der Abfragezeichenfolge verwendet werden. In diesem Fall jeweils Teil der Abfragezeichenfolge muss maskiert werden, was nur ein bisschen mehr Arbeit erfordert:

NSMutableCharacterSet * URLQueryPartAllowedCharacterSet; // possibly defined in class extension ...

// ... and built in init or on first use
URLQueryPartAllowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
[URLQueryPartAllowedCharacterSet removeCharactersInString:@"&+=?"]; // %26, %3D, %3F

// then escape variables in the URL, such as values in the query and any fragment:
NSString * escapedValue = [anUnescapedValue stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet];
NSString * escapedFrag = [anUnescapedFrag stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]];
NSString * urlString = [[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext?myparam=%@#%@", escapedValue, escapedFrag];
NSURL * url = [[NSURL alloc] initWithString:urlString];

Das unescapedValue könnte sogar eine vollständige URL sein, beispielsweise für einen Rückruf oder eine Weiterleitung:

NSString * escapedCallbackParamValue = [anAlreadyEscapedCallbackURL stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet];
NSURL * callbackURL = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext?callback=%@", escapedCallbackParamValue]];

Hinweis: Nicht verwenden NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path für eine URL mit einer Abfragezeichenfolge, weil dem Pfad mehr Prozentzeichen hinzugefügt werden.


100
2017-11-28 16:46



NSString *encodedString = [myString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];

Es wird Ihre Zeichenfolge nicht inline ersetzen; Es wird eine neue Zeichenfolge zurückgegeben. Dies ergibt sich aus der Tatsache, dass die Methode mit dem Wort "string" beginnt. Es ist eine bequeme Methode, um eine neue Instanz von NSString basierend auf dem aktuellen NSString zu instanziieren.

Hinweis - diese neue Zeichenfolge wird sein autoreleaseAlso, ruf nicht los, wenn du damit fertig bist.


5
2017-08-06 12:20



NSS-Zeichenfolgen stringByAddingPercentEscapesUsingEncoding: sieht so aus, als ob Sie danach suchen.

BEARBEITEN: Hier ist ein Beispiel mit CFURLCreateStringByAddingPercentEscapes stattdessen. originalString kann entweder ein sein NSString oder ein CFStringRef.

CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, originalString, NULL, CFSTR("!*'();:@&=+@,/?#[]"), kCFStringEncodingUTF8);

Bitte beachten Sie, dass dies nicht getestet wurde. Sie sollten sich die Dokumentationsseite um sicherzustellen, dass Sie die Speicherzuweisungssemantik für CFStringRefdie Idee der gebührenfreien Überbrückung und so weiter.

Außerdem weiß ich nicht (von ganz oben), welche der in der legalURLCharactersToBeEscapedDas Argument wäre sowieso ausgeblendet worden (weil es in URLs illegal ist). Sie können dies überprüfen, obwohl es vielleicht besser ist, nur auf der sicheren Seite zu sein und direkt die Zeichen anzugeben, die Sie maskieren möchten.

Ich mache diese Antwort zu einem Community-Wiki, damit Leute mit mehr Kenntnissen über CoreFoundation Verbesserungen vornehmen können.


5
2017-09-14 16:32



Dem RFC3986-Standard folgend, verwende ich für die Codierung von URL-Komponenten Folgendes:

// https://tools.ietf.org/html/rfc3986#section-2.2
let rfc3986Reserved = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?#[]")
let encoded = "email+with+plus@example.com".stringByAddingPercentEncodingWithAllowedCharacters(rfc3986Reserved.invertedSet)

Ausgabe: email%2Bwith%2Bplus%40example.com


4
2017-09-01 16:13



Wenn Sie verwenden ASI HttpRequest-Bibliothek In Ihrem objective-c-Programm, das ich nicht hoch genug empfehlen kann, können Sie die API-API "encodeURL" für ihr ASIFormDataRequest-Objekt verwenden. Leider ist die API nicht statisch, daher lohnt es sich vielleicht, eine Erweiterung zu erstellen, die ihre Implementierung in Ihrem Projekt verwendet.

Der Code, der direkt aus dem ASIFormDataRequest.m für die encodeURL-Implementierung kopiert wurde, lautet:

- (NSString*)encodeURL:(NSString *)string
{
    NSString *newString = NSMakeCollectable([(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding([self stringEncoding])) autorelease]);
    if (newString) {
        return newString;
    }
    return @"";
}

Wie Sie sehen können, ist es im Wesentlichen ein Wrapper um CFURLCreateStringByAddingPercentEscapes Das kümmert sich um alle Zeichen, die ordnungsgemäß maskiert werden sollten.


2
2018-02-25 18:05



Bevor ich Robs Antwort bemerkte, die anscheinend gut funktioniert und bevorzugt wird, da sie sauberer ist, habe ich Daves Antwort auf Swift portiert. Ich werde es hier lassen, falls jemand interessiert ist:

public extension String {

    // For performance, I've replaced the char constants with integers, as char constants don't work in Swift.

    var URLEncodedValue: String {
        let output = NSMutableString()
        guard let source = self.cStringUsingEncoding(NSUTF8StringEncoding) else {
            return self
        }
        let sourceLen = source.count

        var i = 0
        while i < sourceLen - 1 {
            let thisChar = source[i]
            if thisChar == 32 {
                output.appendString("+")
            } else if thisChar == 46 || thisChar == 45 || thisChar == 95 || thisChar == 126 ||
                (thisChar >= 97 && thisChar <= 122) ||
                (thisChar >= 65 && thisChar <= 90) ||
                (thisChar >= 48 && thisChar <= 57) {
                    output.appendFormat("%c", thisChar)
            } else {
                output.appendFormat("%%%02X", thisChar)
            }

            i++
        }

        return output as String
    }
}

0
2017-10-12 19:55