Objective-c iPhone-процент кодирует строку?

Я хотел бы получить процент закодированной строки для этих конкретных букв, как это сделать в объективе-c?

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

Вики-энциклопедия

Пожалуйста, проверьте эту строку и посмотрите, работает ли она:

 myURL = @"someurl/somecontent" 

Я бы хотел, чтобы строка выглядела так:

 myEncodedURL = @"someurl%2Fsomecontent" 

Я попытался с stringByAddingPercentEscapesUsingEncoding: NSASCIIStringEncoding уже, но он не работает, результат все тот же, что и исходная строка. Пожалуйста посоветуй.

Я обнаружил, что и stringByAddingPercentEscapesUsingEncoding: и CFURLCreateStringByAddingPercentEscapes() неадекватны. Метод NSString пропускает довольно много символов, и функция CF только позволяет вам указать, какие (конкретные) символы вы хотите избежать. Правильная спецификация заключается в том, чтобы избежать всех символов, кроме небольшого набора.

Чтобы исправить это, я создал метод категории NSString для правильной кодировки строки. Он будет кодировать все EXCEPT [a-zA-Z0-9.-_~] И будет также кодировать пробелы как + (в соответствии с этой спецификацией ). Он также будет правильно обрабатывать кодировку символов Юникода.

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

У iOS 7 SDK теперь есть лучшая альтернатива stringByAddingPercentEscapesUsingEncoding , которая позволяет вам указать, что вы хотите, чтобы все символы были экранированы, за исключением определенных разрешенных. Он работает хорошо, если вы создаете URL-адрес по частям:

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

Хотя реже, чем другие части URL-адреса будут переменными, в категории NSURLUtilities есть константы:

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

[NSCharacterSet URLQueryAllowedCharacterSet] включает все символы, разрешенные в части запроса URL (часть, начинающаяся с ? И перед # для fragmentа, если таковая имеется), включая ? и символы & или = , которые используются для разграничения имен и значений параметров. Для параметров запроса с буквенно-цифровыми значениями любой из этих символов может быть включен в значения переменных, используемых для построения строки запроса. В этом случае каждая часть строки запроса должна быть экранирована, что требует немного больше работы:

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

unescapedValue может быть даже целым URL-адресом, например, для обратного вызова или перенаправления:

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

Примечание. Не используйте NSURL initWithScheme:(NSString *)scheme host:(NSString *)host path:(NSString *)path для URL-адреса с строкой запроса, потому что он добавит больше процентов экранов в путь.

 NSString *encodedString = [myString stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; 

Он не заменит вашу строку inline; он вернет новую строку. Это связано с тем, что метод начинается со слова «строка». Это удобный способ создать экземпляр нового экземпляра NSString на основе текущего NSString.

Обратите внимание, что новая строка будет autorelease ‘d, поэтому не звоните на нее, когда вы закончите с ней.

NSString’s stringByAddingPercentEscapesUsingEncoding: выглядит так, как вы.

EDIT : Вот пример использования CFURLCreateStringByAddingPercentEscapes . originalString может быть либо NSString либо CFStringRef .

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

Обратите внимание, что это не проверено. Вы должны взглянуть на страницу документации, чтобы убедиться, что вы понимаете семантику выделения памяти для CFStringRef , идею бесплатного моста и т. Д.

Кроме того, я не знаю (с моей точки зрения), какой из символов, указанных в аргументе legalURLCharactersToBeEscaped был бы экранирован в любом случае (из-за незаконности в URL-адресах). Вы можете проверить это, хотя, возможно, лучше просто быть в безопасности и напрямую указывать символы, которые вы хотите избежать.

Я делаю этот ответ на wiki сообщества, чтобы люди с более глубокими знаниями о CoreFoundation могли делать улучшения.

Следуя стандарту RFC3986, вот что я использую для кодирования URL-компонентов:

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

Выход: email%2Bwith%2Bplus%40example.com

Если вы используете библиотеку ASI HttpRequest в своей программе объектно-с, которую я не могу рекомендовать достаточно высоко, то вы можете использовать API-интерфейс «encodeURL» для своего объекта ASIFormDataRequest. К сожалению, API не является статическим, поэтому, возможно, стоит создать расширение, используя его реализацию в вашем проекте.

Код, скопированный прямо из ASIFormDataRequest.m для реализации encodeURL, это:

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

Как вы можете видеть, это, по сути, shell вокруг CFURLCreateStringByAddingPercentEscapes которая заботится обо всех символах, которые должны быть надлежащим образом экранированы.

Прежде чем я заметил ответ Роба, который, кажется, работает хорошо и предпочитается, поскольку он чище, я пошел вперед и поместил ответ Дейва на Свифта. Я оставлю его здесь, если кто-то заинтересован:

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

В Swift4:

  var str = "someurl/somecontent" let percentEncodedString = str.addingPercentEncoding(withAllowedCharacters: .alphanumerics) 
  • Тип аксессуара UITableViewCell, проверенный на доступ и установка других непроверенных
  • Как обрабатывать дублируемую символьную ошибку от сторонних библиотек?
  • Ошибка сборки Xcode «Неопределенные символы для архитектуры x86_64»
  • Метод Swizzle на устройстве iPhone
  • Аккордеонная ячейка таблицы - Как динамически расширять / сокращать uitableviewcell?
  • Определение типа устройства
  • Можем ли мы пригласить людей использовать наше приложение или отправить запрос друга из приложения через Facebook в iOS 5?
  • Простое обнаружение движения iPhone
  • Как создать глобальные функции в Objective-C
  • Преимущества, проблемы, примеры добавления другого UIWindow в приложение iOS?
  • UITableViewCell расширяется по клику
  • Давайте будем гением компьютера.