Odpowiedzi:
Ucieczka przed postaciami, które chcesz, to trochę więcej pracy.
Przykładowy kod
iOS7 i nowsze:
NSString *unescaped = @"http://www";
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(@"escapedString: %@", escapedString);
Wyjście NSLog:
escapedString: http% 3A% 2F% 2Fwww
Poniżej przedstawiono przydatne zestawy znaków do kodowania adresów URL:
URLFragmentAllowedCharacterSet "#%<>[\]^`{|}
URLHostAllowedCharacterSet "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet "#%<>[\]^`{|}
URLUserAllowedCharacterSet "#%/:<>?@[\]^`
Tworzenie zestawu znaków łączącego wszystkie powyższe:
NSCharacterSet *URLCombinedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>?@[\\]^`{|}"] invertedSet];
Tworzenie Base64
W przypadku zestawu znaków Base64:
NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet];
Dla Swift 3.0:
var escapedString = originalString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)
Dla Swift 2.x:
var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())
Uwaga: stringByAddingPercentEncodingWithAllowedCharacters
zakoduje również znaki UTF-8 wymagające kodowania.
Przed iOS7 używaj Core Foundation
przy użyciu Core Foundation z ARC:
NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
NULL,
(__bridge CFStringRef) unescaped,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]\" "),
kCFStringEncodingUTF8));
Korzystanie z Core Foundation bez ARC:
NSString *escapedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)unescaped,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]\" "),
kCFStringEncodingUTF8);
Uwaga: -stringByAddingPercentEscapesUsingEncoding
nie wygeneruje prawidłowego kodowania, w tym przypadku nie zakoduje niczego zwracającego ten sam ciąg.
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding
koduje 14 znaków:
`#% ^ {} [] | \" <> plus znak spacji jako procent ucieczki.
testString:
" `~!@#$%^&*()_+-={}[]|\\:;\"'<,>.?/AZaz"
encodedString:
"%20%60~!@%23$%25%5E&*()_+-=%7B%7D%5B%5D%7C%5C:;%22'%3C,%3E.?/AZaz"
Uwaga: zastanów się, czy ten zestaw znaków spełnia Twoje potrzeby, jeśli nie, zmień je w razie potrzeby.
Znaki RFC 3986 wymagające kodowania (% dodane, ponieważ jest to znak prefiksu kodowania):
"! # $ & '() * +, /:; =? @ []%"
Niektóre „niezarezerwowane znaki” są dodatkowo zakodowane:
"\ n \ r \"% -. <> \ ^ _ `{|} ~"
-stringByAddingPercentEscapesUsingEncoding
metody NSString .
stringByAddingPercentEscapesUsingEncoding
zachowanie. Koduje tylko „&” i „=” lub coś takiego niedorzecznego.
NSString
with characterSetWithCharactersInString
, weź odwrotność z invertedSet
i użyj tego z stringByAddingPercentEncodingWithAllowedCharacters
. Na przykład zobacz tę odpowiedź SO .
Nazywa się to kodowaniem adresów URL . Więcej tutaj .
-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
CFStringConvertNSStringEncodingToEncoding(encoding));
}
CFURLCreateStringByAddingPercentEscapes()
jest przestarzałe. Użyj [NSString stringByAddingPercentEncodingWithAllowedCharacters:]
zamiast tego.
To nie jest moje rozwiązanie. Ktoś inny napisał w stackoverflow, ale zapomniałem jak.
Jakoś to rozwiązanie działa „dobrze”. Obsługuje znaki diakrytyczne, chińskie i prawie wszystko inne.
- (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;
}
Gdyby ktoś mi powiedział, kto napisał ten kod, będę bardzo wdzięczny. Zasadniczo ma pewne wyjaśnienie, dlaczego ten zakodowany ciąg będzie dekodował dokładnie tak, jak sobie życzy.
Zmodyfikowałem trochę jego rozwiązanie. Wolę, aby przestrzeń była reprezentowana za pomocą% 20 zamiast +. To wszystko.
NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );
NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];
Może to działać w ARC Objective C. Użyj CFBridgingRelease, aby rzutować obiekt w stylu Core Foundation jako obiekt Objective-C i przenieść własność obiektu na ARC .Patrz Funkcja CFBridgingRelease tutaj.
+ (NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes
(kCFAllocatorDefault,
(__bridge CFStringRef)string,
NULL,
CFSTR("!*'();:@&=+$,/?%#[]"),
kCFStringEncodingUTF8)
);}
Swift iOS:
Tylko dla informacji: użyłem tego:
extension String {
func urlEncode() -> CFString {
return CFURLCreateStringByAddingPercentEscapes(
nil,
self,
nil,
"!*'();:@&=+$,/?%#[]",
CFStringBuiltInEncodings.UTF8.rawValue
)
}
}// end extension String
Oto czego używam. Pamiętaj, że musisz użyć@autoreleasepool
funkcji lub program może zawiesić lub zablokować IDE. Musiałem trzykrotnie zrestartować IDE, zanim zdałem sobie sprawę z poprawki. Wygląda na to, że ten kod jest zgodny z ARC.
To pytanie było zadawane wiele razy i udzielono wielu odpowiedzi, ale niestety wszystkie wybrane (i kilka innych sugerowanych) są błędne.
Oto ciąg testowy, którego użyłem: This is my 123+ test & test2. Got it?!
Oto moje metody klasy Objective 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 implementuje to w swoim programie Google Toolbox dla komputerów Mac . To dobre miejsce, aby zobaczyć, jak to robią. Inną opcją jest dołączenie Toolbox i użycie ich implementacji.
Sprawdź implementację tutaj . (Co sprowadza się dokładnie do tego, co ludzie tutaj publikowali).
Oto jak robię to szybko.
extension String {
func encodeURIComponent() -> String {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
}
func decodeURIComponent() -> String {
return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
}
}
// użyj metody instancji NSString w następujący sposób:
+ (NSString *)encodeURIComponent:(NSString *)string
{
NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
+ (NSString *)decodeURIComponent:(NSString *)string
{
NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
pamiętaj, że powinieneś kodować lub dekodować tylko wartość parametru, a nie cały adres URL, o który prosisz.
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~
- żadne z poniższych rozwiązań nie wydaje się rozwiązać tego problemu!