Ich möchte die prozentual codierte Zeichenfolge für diese spezifischen Buchstaben erhalten. Wie geht das in Ziel-C?
Reserved characters after percent-encoding
! * ' ( ) ; : @ & = + $ , / ? # [ ]
%21 %2A %27 %28 %29 %3B %3A %40 %26 %3D %2B %24 %2C %2F %3F %23 %5B %5D
Bitte testen Sie mit dieser Zeichenfolge und prüfen Sie, ob sie funktioniert:
myURL = @"someurl/somecontent"
Ich möchte, dass die Zeichenfolge wie folgt aussieht:
myEncodedURL = @"someurl%2Fsomecontent"
Ich habe es schon mit versucht, stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding
aber es funktioniert nicht, das Ergebnis ist immer noch das gleiche wie die ursprüngliche Zeichenfolge. Bitte beraten.
iphone
objective-c
Hoang Pham
quelle
quelle
%
Zeichen selbst URL-codiert sein sollte. Auf diese Weise wird ein String - Eingang wie%2F
verwandelt sich in%252F
. Ich würde auch vorschlagen, das Leerzeichen (%20
) zu dieser Liste hinzuzufügen .Antworten:
Ich habe festgestellt, dass beide
stringByAddingPercentEscapesUsingEncoding:
undCFURLCreateStringByAddingPercentEscapes()
unzureichend sind. Bei derNSString
Methode fehlen einige Zeichen, und mit der CF-Funktion können Sie nur angeben, welchen (bestimmten) Zeichen Sie entkommen möchten. Die richtige Spezifikation besteht darin, alle Zeichen außer einem kleinen Satz zu maskieren.Um dies zu beheben, habe ich eine
NSString
Kategoriemethode erstellt, um eine Zeichenfolge ordnungsgemäß zu codieren. Es codiert prozentual alles AUSSER[a-zA-Z0-9.-_~]
und codiert auch Leerzeichen als+
(gemäß dieser Spezifikation ). Die Codierung von Unicode-Zeichen wird ebenfalls ordnungsgemäß verarbeitet.- (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; }
quelle
Das iOS 7 SDK bietet jetzt eine bessere Alternative
stringByAddingPercentEscapesUsingEncoding
, mit der Sie festlegen können, 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 seltener vorkommt, dass die anderen Teile der URL Variablen sind, gibt es in der Kategorie NSURLUtilities auch Konstanten für diese:
[NSCharacterSet URLHostAllowedCharacterSet] [NSCharacterSet URLUserAllowedCharacterSet] [NSCharacterSet URLPasswordAllowedCharacterSet] [NSCharacterSet URLPathAllowedCharacterSet] [NSCharacterSet URLFragmentAllowedCharacterSet]
[NSCharacterSet URLQueryAllowedCharacterSet]
Enthält alle Zeichen, die im Abfrageteil der URL zulässig sind (der Teil, der mit dem?
und vor dem#
für ein Fragment beginnt , falls vorhanden), einschließlich der Zeichen?
und&
oder=
, die zur Begrenzung der Parameternamen und -werte verwendet werden. Bei Abfrageparametern mit alphanumerischen Werten kann eines dieser Zeichen in den Werten der Variablen enthalten sein, die zum Erstellen der Abfragezeichenfolge verwendet werden. In diesem Fall muss jeder Teil der Abfragezeichenfolge maskiert werden, was nur ein wenig 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 ganze URL, wie für einen Rückruf oder Umleitung sein:NSString * escapedCallbackParamValue = [anAlreadyEscapedCallbackURL stringByAddingPercentEncodingWithAllowedCharacters:URLQueryPartAllowedCharacterSet]; NSURL * callbackURL = [[NSURL alloc] initWithString:[[NSString alloc] initWithFormat:@"http://ExampleOnly.com/path.ext?callback=%@", escapedCallbackParamValue]];
Hinweis: Nicht
NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path
für eine URL mit einer Abfragezeichenfolge verwenden, da dadurch mehr prozentuale Escapezeichen zum Pfad hinzugefügt werden.quelle
[URLQueryPartAllowedCharacterSet removeCharactersInRange:NSMakeRange('+', 1)];
aber ansonsten ist dieser Code perfekt, um Zeichenfolgen zu entkommen. Danke!URLQueryPartAllowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy]; [URLQueryPartAllowedCharacterSet removeCharactersInString:@"?&=@+/'"];
Ich habe auch 100.000 Iterationen auf einem Mac getestet und festgestellt, dass dies durchweg etwas schneller ist als einremoveCharactersInRange:
mehrmaliger Aufruf .%
? sollte es nicht auch codiert werden, wenn es im Wert ist?NSString *encodedString = [myString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
Es wird Ihre Inline-Zeichenfolge nicht ersetzen. Es wird eine neue Zeichenfolge zurückgegeben. Dies wird durch die Tatsache impliziert, dass die Methode mit dem Wort "string" beginnt. Es ist eine bequeme Methode, eine neue Instanz von NSString basierend auf dem aktuellen NSString zu instanziieren.
Hinweis - Die neue Zeichenfolge wird
autorelease
"d" sein. Rufen Sie also nicht "release" auf, wenn Sie damit fertig sind.quelle
StringByAddingPercentEscapesUsingEncoding von NSString: sieht aus wie das, wonach Sie suchen .BEARBEITEN : Hier ist ein Beispiel, das
CFURLCreateStringByAddingPercentEscapes
stattdessen verwendet wird.originalString
kann entweder einNSString
oder ein seinCFStringRef
.CFStringRef newString = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, originalString, NULL, CFSTR("!*'();:@&=+@,/?#[]"), kCFStringEncodingUTF8);
Bitte beachten Sie, dass dies nicht getestet wurde. Sie sollten sich die Dokumentationsseite ansehen , um sicherzustellen, dass Sie die Semantik der Speicherzuweisung für
CFStringRef
, die Idee der gebührenfreien Überbrückung usw. verstehen .Außerdem weiß ich nicht (auf Anhieb), welches der im
legalURLCharactersToBeEscaped
Argument angegebenen Zeichen ohnehin maskiert worden wäre (da es in URLs illegal ist). Möglicherweise möchten Sie dies überprüfen, obwohl es vielleicht besser ist, nur auf der sicheren Seite zu sein und direkt die Zeichen anzugeben, die maskiert werden sollen.Ich mache diese Antwort zu einem Community-Wiki, damit Leute mit mehr Wissen über CoreFoundation Verbesserungen vornehmen können.
quelle
NSStringEncoding
Wert für das zu geben, was Sie wollen. Sie können stattdessen versuchenCFURLCreateStringByAddingPercentEscapes
( developer.apple.com/mac/library/documentation/CoreFoundation/… ) - Sie können damit die zu entkommenden Zeichen direkt angeben.NSString
undCFStringRef
sind "gebührenfrei überbrückt", was bedeutet, dass sie austauschbar an die Funktionen des anderen weitergegeben werden können.Nach dem RFC3986-Standard verwende ich Folgendes zum Codieren von URL-Komponenten:
// https://tools.ietf.org/html/rfc3986#section-2.2 let rfc3986Reserved = NSCharacterSet(charactersInString: "!*'();:@&=+$,/?#[]") let encoded = "[email protected]".stringByAddingPercentEncodingWithAllowedCharacters(rfc3986Reserved.invertedSet)
Ausgabe:
email%2Bwith%2Bplus%40example.com
quelle
Wenn Sie die ASI HttpRequest-Bibliothek in Ihrem Objective-C-Programm verwenden, was ich nicht genug empfehlen kann, können Sie die Helfer-API "encodeURL" für das ASIFormDataRequest-Objekt verwenden. Leider ist die API nicht statisch, daher lohnt es sich möglicherweise, eine Erweiterung mithilfe ihrer Implementierung in Ihrem Projekt zu erstellen.
Der Code, der direkt aus ASIFormDataRequest.m für die Implementierung von encodeURL 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, handelt es sich im Wesentlichen um einen Wrapper
CFURLCreateStringByAddingPercentEscapes
, der sich um alle Zeichen kümmert, die ordnungsgemäß maskiert werden sollten.quelle
Bevor ich Robs Antwort bemerkte, die gut zu funktionieren scheint und als sauberer bevorzugt wird, portierte ich Daves Antwort auf Swift. Ich lasse es hier, 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 } }
quelle
let string = "te&st"; print(string.URLEncodedValue)
In Swift4:
var str = "someurl/somecontent" let percentEncodedString = str.addingPercentEncoding(withAllowedCharacters: .alphanumerics)
quelle