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 versucht mit der stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding bereits, aber es funktioniert nicht, das Ergebnis ist immer noch das gleiche wie die ursprüngliche Zeichenfolge. Bitte um Rat.

Ich habe festgestellt, dass sowohl stringByAddingPercentEscapesUsingEncoding: und CFURLCreateStringByAddingPercentEscapes() unzureichend sind. Die NSString Methode verpasst einige Zeichen, und die CF-function lässt Sie nur sagen, welche (spezifischen) Zeichen Sie verlassen möchten. Die korrekte Spezifikation besteht darin, alle Zeichen außer einem kleinen Satz zu entkommen.

Um dies zu beheben, habe ich eine NSString Kategorie-Methode erstellt, um eine Zeichenfolge ordnungsgemäß zu codieren. Es wird Prozent codieren alles außer [a-zA-Z0-9.-_~] Und codiert auch Leerzeichen als + (gemäß dieser 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; } 

Das iOS 7 SDK bietet jetzt eine bessere Alternative zu stringByAddingPercentEscapesUsingEncoding , mit der Sie festlegen können, dass alle Zeichen außer bestimmten zulässigen Zeichen stringByAddingPercentEscapesUsingEncoding 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] enthält alle Zeichen, die im Abfrageteil der URL zulässig sind (der Teil, der mit dem ? [NSCharacterSet URLQueryAllowedCharacterSet] und vor dem # für ein Fragment, falls vorhanden) einschließlich ? und die Zeichen & or = , die zum Abgrenzen der Parameternamen und -werte verwendet 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 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]; 

Der unescapedValue könnte sogar eine vollständige URL sein, etwa für einen Callback oder Redirect:

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

Hinweis: Verwenden Sie NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path für eine URL mit einer NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path da der Pfad mehr Prozentzeichen enthält.

 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.

Beachten Sie, dass die neue Zeichenfolge autorelease Rufen Sie die Freigabe nicht an, wenn Sie fertig sind.

NSString’s stringByAddingPercentEscapesUsingEncoding: sieht so aus, als ob Sie danach suchen .

Bearbeiten : Hier ist ein Beispiel mit CFURLCreateStringByAddingPercentEscapes stattdessen. originalString kann entweder ein 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 ansehen, um sicherzustellen, dass Sie die Speicherresortierungssemantik für CFStringRef , die Idee des gebührenfreien Bridging usw. verstehen.

Außerdem weiß ich nicht (von ganz oben), welches der im legalURLCharactersToBeEscaped Argument angegebenen Zeichen sowieso legalURLCharactersToBeEscaped (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.

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

Wenn Sie in Ihrem objective-c-Programm die ASI HttpRequest-Bibliothek verwenden , die 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 , der sich um alle Zeichen kümmert, die ordnungsgemäß CFURLCreateStringByAddingPercentEscapes sollten.

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

In Swift4:

  var str = "someurl/somecontent" let percentEncodedString = str.addingPercentEncoding(withAllowedCharacters: .alphanumerics)