การเข้ารหัส Objective-C และ Swift URL


137

ฉันมีสิ่งNSStringนี้:

http://www.

แต่ฉันต้องการแปลงเป็น:

http%3A%2F%2Fwww.

ฉันจะทำสิ่งนี้ได้อย่างไร


1
ฉันมีสตริงที่เข้ารหัสเช่นùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~- ดูเหมือนว่าไม่มีวิธีการแก้ปัญหาด้านล่างนี้!
Mahendra Liya

คำตอบ:


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

สร้าง Base64

ในกรณีของตัวละคร 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 ที่ต้องการการเข้ารหัสด้วย

Pre 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
Mike Weller

2
อ่าใช่ตอนนี้ฉันจำได้ว่าstringByAddingPercentEscapesUsingEncodingพฤติกรรมขี้ขลาด มันเข้ารหัสเฉพาะ '&' และ '=' หรือสิ่งที่ไร้สาระเช่นนั้น
Mike Weller

2
ตามRFC1738คุณจะต้องเข้ารหัสอักขระเพิ่มเติมเช่นกัน ดังนั้นแม้ว่าสิ่งนี้จะตอบคำถามของ OP แต่ก็มีข้อ จำกัด ด้านประโยชน์เป็นตัวเข้ารหัส URL อเนกประสงค์ ตัวอย่างเช่นจะไม่จัดการกับตัวอักษรและตัวเลขที่ไม่ใช่ตัวอักษรเช่นเครื่องหมายอุมเลาต์ของเยอรมัน
Alex Nauda

3
สิ่งนี้ใช้ไม่ได้ (สำหรับส่วน iOS 7) สิ่งนี้ไม่แปลง & เป็น% 26
coolcool1994

1
สร้างชุดตัวอักษรที่คุณต้องการจากNSStringที่มีการcharacterSetWithCharactersInStringใช้สิ่งที่ตรงกันข้ามกับและการใช้งานที่มีinvertedSet stringByAddingPercentEncodingWithAllowedCharactersสำหรับตัวอย่างดูคำตอบ SOนี้
zaph

22

มันเรียกว่าการเข้ารหัส URL เพิ่มเติมที่นี่

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

3
สิ่งนี้จะมีประโยชน์มากขึ้นหากเนื้อหาบางส่วนจากลิงก์ที่คุณโพสต์รวมอยู่ในคำตอบ
chown

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

[ตนเอง UTF8String] คืออะไร
Yuchao Zhou

1
@ yuchaozh นี่คือฟังก์ชั่นที่คุณใส่ในหมวดหมู่ของ NSString ดังนั้นตัวเองคือ NSStirng และ [self UTF8String] จะกลับมาโดยสมมติว่าสตริงนั้นอยู่ในรูปแบบ UTF8
Kelsey

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 รหัสนี้เกี่ยวกับพารามิเตอร์การเข้ารหัส ในการเข้ารหัสสตริงการส่งผ่านที่อยู่ทั้งหมดแทน "พารามิเตอร์"
Zahi

สิ่งนี้ได้ผลสำหรับฉัน ... เข้ารหัสแม้กระทั่งอักขระ & ที่ฉันมีปัญหาด้วย
ВикторИванов

3

สิ่งนี้สามารถทำงานได้ใน Objective C ARC ใช้ CFBridgingRelease เพื่อโยนวัตถุสไตล์รากฐานหลักเป็นวัตถุ 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 Toolbox for 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: escapes เท่านั้นและ = :-(
Sébastien Stormacq

1
ถูกต้องดังนั้นสิ่งต่างๆเช่น + จะไม่ถูกเข้ารหัสเมื่อจำเป็นต้องเป็น ดังนั้นอย่าใช้คำตอบข้างต้น
John Ballinger

-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 );
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.