Відповіді:
Щоб уникнути бажаних персонажів - це трохи більше роботи.
Приклад коду
iOS7 і вище:
NSString *unescaped = @"http://www";
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(@"escapedString: %@", escapedString);
Вихід NSLog:
escapedString: http% 3A% 2F% 2Fwww
Наступні корисні набори символів для кодування URL-адрес:
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}
URLHostAllowedCharacterSet "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet "#%<>[\]^`{|}
URLUserAllowedCharacterSet "#%/:<>?@[\]^`
Створення набору символів, що поєднує все вищезазначене:
NSCharacterSet *URLCombinedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>?@[\\]^`{|}"] invertedSet];
Створення бази64
У випадку набору символів Base64:
NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet];
Для Swift 3.0:
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)
Для Swift 2.x:
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
Примітка: stringByAddingPercentEncodingWithAllowedCharacters
також буде кодувати UTF-8 символів, які потребують кодування.
Попередньо iOS7 використовуйте Core Foundation,
використовуючи Core Foundation із ARC:
NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) unescaped,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]\" "),
kCFStringEncodingUTF8));
Використання Core Foundation без ARC:
NSString *escapedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unescaped,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]\" "),
kCFStringEncodingUTF8);
Примітка: -stringByAddingPercentEscapesUsingEncoding
не створить правильне кодування, в цьому випадку він не буде кодувати нічого, що повертає ту саму рядок.
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding
кодує 14 символів:
`#% ^ {} [] | \" <> плюс символ пробілу у відсотках.
testString:
" `~!@#$%^&*()_+-={}[]|\\:;\"'<,>.?/AZaz"
encodedString:
"%20%60~!@%23$%25%5E&*()_+-=%7B%7D%5B%5D%7C%5C:;%22'%3C,%3E.?/AZaz"
Примітка. Подумайте, чи відповідає цей набір символів вашим потребам, чи не змінюйте їх у міру необхідності.
Символи RFC 3986, що потребують кодування (% додано, оскільки це символ префіксу кодування):
"! # $ & '() * +, /:; =? @ []%"
Деякі "незарезервовані символи" додатково кодуються:
"\ n \ r \"% -. <> \ ^ _ `{|} ~"
-stringByAddingPercentEscapesUsingEncoding
метод NSString .
stringByAddingPercentEscapesUsingEncoding
поведінку. Він кодує лише "&" і "=" або щось смішне подібне.
Це називається кодування URL-адрес . Більше тут .
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
CFURLCreateStringByAddingPercentEscapes()
застаріло. Використовуйте [NSString stringByAddingPercentEncodingWithAllowedCharacters:]
замість цього.
Це не моє рішення. Хтось ще писав у stackoverflow, але я забув, як.
Якось це рішення працює «добре». Він обробляє діакритичні, китайські символи та багато іншого.
- (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;
}
Якщо хтось скаже мені, хто написав цей код, я дуже вдячний. В основному він має деякі пояснення, чому ця закодована рядок буде декодувати саме так, як вона хотіла.
Я трохи змінив його рішення. Мені подобається, щоб простір був представлений% 20, а не +. Це все.
NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );
NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];
Це може працювати в Objective C ARC.Use CFBridgingRelease для передачі об'єкта в стилі Core Foundation як об'єкта Objective-C і передачі права власності на об'єкт ARC. Подивіться тут функцію CFBridgingRelease .
+ (NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes
(kCFAllocatorDefault,
(__bridge CFStringRef)string,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
kCFStringEncodingUTF8)
);}
Швидкий iOS:
Тільки для інформації: я використав це:
extension String {
func urlEncode() -> CFString {
return CFURLCreateStringByAddingPercentEscapes(
nil,
self,
nil,
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
}
}// end extension String
Ось що я використовую. Зверніть увагу, що ви повинні використовувати@autoreleasepool
функцією, або програма може ладу або заблокувати IDE. Мені довелося тричі перезапустити IDE, поки я не зрозумів виправлення. Схоже, цей код сумісний з ARC.
Це питання задавали багато разів, і багато відповідей дано, але, на жаль, всі обрані (та ще кілька запропонованих) помиляються.
Ось тестовий рядок, який я використав: This is my 123+ test & test2. Got it?!
Це мої методи класу C ++ класу:
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;
}
}
Google реалізує це у своїй панелі інструментів Google для Mac . Тож це гарне місце для досягнення максимуму, як вони це роблять. Інший варіант - включити панель інструментів і використовувати їх реалізацію.
Ознайомтеся з реалізацією тут . (Що зводиться до саме того, що тут публікували люди).
Ось як я це роблю швидко.
extension String {
func encodeURIComponent() -> String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
}
func decodeURIComponent() -> String {
return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
}
}
// використовувати метод екземпляра NSString таким чином:
+ (NSString *)encodeURIComponent:(NSString *)string
{
NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
+ (NSString *)decodeURIComponent:(NSString *)string
{
NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
Пам'ятайте, ви повинні робити кодування або декодування лише для значення вашого параметра, а не всі URL-адреси, які ви запитуєте.
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 );
ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~
- жоден із наведених нижче рішень, схоже, не вирішує це питання!