Об'єктивне кодування C та Swift URL


137

У мене є NSStringтакий:

http://www.

але я хочу перетворити це на:

http%3A%2F%2Fwww.

Як я можу це зробити?


1
У мене є зашифрований рядок на кшталт ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~- жоден із наведених нижче рішень, схоже, не вирішує це питання!
Махендра Лія

Відповіді:


324

Щоб уникнути бажаних персонажів - це трохи більше роботи.

Приклад коду

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 \"% -. <> \ ^ _ `{|} ~"


1
Також зверніть увагу, що ви можете використовувати -stringByAddingPercentEscapesUsingEncodingметод NSString .
Майк Веллер

2
Ага так, зараз я пам’ятаю прикольну stringByAddingPercentEscapesUsingEncodingповедінку. Він кодує лише "&" і "=" або щось смішне подібне.
Майк Веллер

2
Згідно RFC1738 вам також потрібно буде кодувати додаткові символи. Отже, хоча це відповідає на питання ОП, воно має обмежену корисність як кодер URL загального призначення. Наприклад, він не обробляє не алфавітні цифри, такі як німецький умулат.
Алекс Науда

3
Це не працює (для iOS 7 частина). Це не перетворює & в% 26.
coolcool1994

1
Створити набір символів , вам потрібно від NSStringс characterSetWithCharactersInString, взяти зворотний з invertedSetі використовувати його з stringByAddingPercentEncodingWithAllowedCharacters. Для прикладу див. Цю відповідь .
zaph

22

Це називається кодування URL-адрес . Більше тут .

-(NSString *)urlEncodeUsingEncoding:(NSStringEncoding)encoding {
    return (NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
           (CFStringRef)self,
           NULL,
           (CFStringRef)@"!*'\"();:@&=+$,/?%#[]% ",
           CFStringConvertNSStringEncodingToEncoding(encoding));
}

3
Це було б набагато корисніше, якби у відповідь був включений якийсь вміст із посилань, які ви опублікували.
чауна

1
CFURLCreateStringByAddingPercentEscapes()застаріло. Використовуйте [NSString stringByAddingPercentEncodingWithAllowedCharacters:]замість цього.
Панг

7

Це не моє рішення. Хтось ще писав у 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, а не +. Це все.


Оригінальний код: stackoverflow.com/questions/3423545 / ...
hsoi

що таке [self UTF8String]?
Ючао Чжоу

1
@yuchaozh - це функція, яку ви ставите всередину категорії NSString. Отже, self є NSStirng і [self UTF8String] повертає, припускаючи, його рядок у форматі UTF8.
Келсі

4
 NSString * encodedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(NUL,(CFStringRef)@"parameter",NULL,(CFStringRef)@"!*'();@&+$,/?%#[]~=_-.:",kCFStringEncodingUTF8 );

NSURL * url = [[NSURL alloc] initWithString:[@"address here" stringByAppendingFormat:@"?cid=%@",encodedString, nil]];

1
випустити encodedString та URL. цей код стосується параметра кодування. Для кодування цілої адреси передайте рядок замість "параметра".
Захі

Це працювало для мене ... кодувало навіть & характер, з яким у мене виникли проблеми.
Віктор Іванов

3

Це може працювати в 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)
                         );}

2

Швидкий iOS:

Тільки для інформації: я використав це:

extension String {

    func urlEncode() -> CFString {
        return CFURLCreateStringByAddingPercentEscapes(
            nil,
            self,
            nil,
            "!*'();:@&=+$,/?%#[]",
            CFStringBuiltInEncodings.UTF8.rawValue
        )
    }

}// end extension String

1
NSString *str = (NSString *)CFURLCreateStringByAddingPercentEscapes(
                             NULL,
                             (CFStringRef)yourString, 
                             NULL, 
                             CFSTR("/:"), 
                             kCFStringEncodingUTF8);

Вам потрібно буде випустити або автоматично випустити strсамостійно.


1

Ось що я використовую. Зверніть увагу, що ви повинні використовувати@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;
    }
}

0

Google реалізує це у своїй панелі інструментів Google для Mac . Тож це гарне місце для досягнення максимуму, як вони це роблять. Інший варіант - включити панель інструментів і використовувати їх реалізацію.

Ознайомтеся з реалізацією тут . (Що зводиться до саме того, що тут публікували люди).


0

Ось як я це роблю швидко.

extension String {
    func encodeURIComponent() -> String {
        return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
    }

    func decodeURIComponent() -> String {
        return self.componentsSeparatedByString("+").joinWithSeparator(" ").stringByRemovingPercentEncoding!
    }
}

-1

// використовувати метод екземпляра NSString таким чином:

+ (NSString *)encodeURIComponent:(NSString *)string
{
NSString *s = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}

+ (NSString *)decodeURIComponent:(NSString *)string
{
NSString *s = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}

Пам'ятайте, ви повинні робити кодування або декодування лише для значення вашого параметра, а не всі URL-адреси, які ви запитуєте.


2
stringByReplacingPercentEscapeusingencoding: втече лише & і = :-(
Sébastien Stormacq

1
Правильно, тому речі типу + не кодуються, коли вони мають бути. Тому не використовуйте вищезгадану відповідь
Джон Баллінгер

-8
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 );
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.