Mã hóa URL Objective-C và Swift


137

Tôi có một cái NSStringnhư thế này:

http://www.

nhưng tôi muốn chuyển đổi nó thành:

http%3A%2F%2Fwww.

Tôi có thể làm cái này như thế nào?


1
Tôi có một chuỗi được mã hóa như ùÕ9y^VêÏÊEØ®.ú/V÷ÅÖêú2Èh~- không có giải pháp nào dưới đây có vẻ giải quyết vấn đề này!
Mahendra Liya

Câu trả lời:


324

Để thoát khỏi các nhân vật bạn muốn là một công việc nhiều hơn một chút.

Mã ví dụ

iOS7 trở lên:

NSString *unescaped = @"http://www";
NSString *escapedString = [unescaped stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLHostAllowedCharacterSet]];
NSLog(@"escapedString: %@", escapedString);

Đầu ra NSLog:

đã thoátString: http% 3A% 2F% 2Fwww

Sau đây là các bộ ký tự mã hóa URL hữu ích:

URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}
URLHostAllowedCharacterSet      "#%/<>?@\^`{|}
URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}
URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}
URLQueryAllowedCharacterSet     "#%<>[\]^`{|}
URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

Tạo một bộ ký tự kết hợp tất cả các mục trên:

NSCharacterSet *URLCombinedCharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@" \"#%/:<>?@[\\]^`{|}"] invertedSet];

Tạo một Base64

Trong trường hợp ký tự Base64:

NSCharacterSet *URLBase64CharacterSet = [[NSCharacterSet characterSetWithCharactersInString:@"/+=\n"] invertedSet];

Đối với Swift 3.0:

var escapedString = originalString.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed)

Đối với Swift 2.x:

var escapedString = originalString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLHostAllowedCharacterSet())

Lưu ý: stringByAddingPercentEncodingWithAllowedCharacterscũng sẽ mã hóa các ký tự UTF-8 cần mã hóa.

Trước iOS7 sử dụng Core Foundation
Sử dụng Core Foundation với ARC:

NSString *escapedString = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(
    NULL,
   (__bridge CFStringRef) unescaped,
    NULL,
    CFSTR("!*'();:@&=+$,/?%#[]\" "),
    kCFStringEncodingUTF8));

Sử dụng Core Foundation không có ARC:

NSString *escapedString = (NSString *)CFURLCreateStringByAddingPercentEscapes(
    NULL,
   (CFStringRef)unescaped,
    NULL,
    CFSTR("!*'();:@&=+$,/?%#[]\" "),
    kCFStringEncodingUTF8);

Lưu ý: -stringByAddingPercentEscapesUsingEncodingsẽ không tạo ra mã hóa chính xác, trong trường hợp này, nó sẽ không mã hóa bất cứ thứ gì trả về cùng một chuỗi.

stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding mã hóa 14 characrters:

`#% ^ {} [] | \" <> cộng với ký tự khoảng trắng là phần trăm thoát.

kiểm tra:

" `~!@#$%^&*()_+-={}[]|\\:;\"'<,>.?/AZaz"  

mã hóaString:

"%20%60~!@%23$%25%5E&*()_+-=%7B%7D%5B%5D%7C%5C:;%22'%3C,%3E.?/AZaz"  

Lưu ý: xem xét nếu bộ ký tự này đáp ứng nhu cầu của bạn, nếu không thay đổi chúng khi cần.

RFC 3986 ký tự yêu cầu mã hóa (% được thêm vì đây là ký tự tiền tố mã hóa):

"! # $ & '() * +, / :; =? @ []%"

Một số "ký tự không được giám sát" được mã hóa bổ sung:

"\ n \ r \"% -. <> \ ^ _ `{|} ~"


1
Cũng lưu ý rằng bạn có thể sử dụng -stringByAddingPercentEscapesUsingEncodingphương pháp của NSString .
Mike Weller

2
À vâng, bây giờ tôi nhớ stringByAddingPercentEscapesUsingEncodinghành vi sôi nổi . Nó chỉ mã hóa '&' và '=' hoặc một cái gì đó vô lý như thế.
Mike Weller

2
Theo RFC1738, bạn cũng cần phải mã hóa các ký tự bổ sung. Vì vậy, mặc dù điều này không trả lời câu hỏi của OP, nhưng nó có giới hạn hữu ích như một bộ mã hóa URL mục đích chung. Ví dụ, nó không xử lý các chữ số không như chữ số tiếng Đức.
Alex Nauda

3
Điều này không hoạt động (đối với phần iOS 7). Điều này không chuyển đổi & thành% 26.
coolcool1994

1
Tạo bộ ký tự bạn cần từ một NSStringvới characterSetWithCharactersInString, lấy nghịch đảo invertedSetvà sử dụng nó với stringByAddingPercentEncodingWithAllowedCharacters. Ví dụ, xem câu trả lời SO này .
zaph

22

Nó được gọi là mã hóa URL . Thêm ở đây .

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

3
Điều này sẽ hữu ích hơn rất nhiều nếu một số nội dung từ các liên kết bạn đã đăng được đưa vào câu trả lời.
chown

1
CFURLCreateStringByAddingPercentEscapes()bị phản đối Sử dụng [NSString stringByAddingPercentEncodingWithAllowedCharacters:]thay thế.
Pang

7

Đây không phải là giải pháp của tôi. Có người khác viết trong stackoverflow nhưng tôi đã quên mất.

Bằng cách nào đó giải pháp này hoạt động "tốt". Nó xử lý các ký tự, ký tự Trung Quốc, và khá nhiều thứ khác.

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

Nếu ai đó sẽ cho tôi biết ai đã viết mã này, tôi sẽ thực sự đánh giá cao nó. Về cơ bản, ông có một số giải thích tại sao chuỗi được mã hóa này sẽ giải mã chính xác như nó muốn.

Tôi sửa đổi giải pháp của mình một chút. Tôi thích không gian được đại diện với% 20 hơn là +. Đó là tất cả.



[tự UTF8String] là gì?
Yuchao Zhou

1
@yuchaozh đây là chức năng mà bạn đặt trong danh mục NSString. Vì vậy, self là NSStirng và [self UTF8String] trả về, giả sử, chuỗi của nó ở định dạng 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
phát hành mã hóaString và url. mã này là về tham số mã hóa. Để mã hóa toàn bộ chuỗi địa chỉ, thay vì "tham số".
Zahi

Điều này làm việc cho tôi ... mã hóa ngay cả & nhân vật mà tôi gặp vấn đề.
Виктор Иванов

3

Điều này có thể hoạt động trong Objective C ARC.Use CFBridgingRelease để truyền đối tượng kiểu Core Foundation thành đối tượng Objective-C và chuyển quyền sở hữu đối tượng sang ARC. Xem chức năng CFBridgingRelease tại đây.

+ (NSString *)encodeUrlString:(NSString *)string {
return CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes
                         (kCFAllocatorDefault,
                          (__bridge CFStringRef)string,
                          NULL,
                          CFSTR("!*'();:@&=+$,/?%#[]"),
                          kCFStringEncodingUTF8)
                         );}

2

Swift iOS:

Chỉ để biết thông tin: Tôi đã sử dụng điều này:

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

Bạn sẽ cần phải phát hành hoặc strtự động phát hành .


1

Đây là những gì tôi sử dụng. Lưu ý rằng bạn phải sử dụng @autoreleasepooltính năng này hoặc chương trình có thể bị sập hoặc khóa IDE. Tôi đã phải khởi động lại IDE của mình ba lần cho đến khi nhận ra cách khắc phục. Dường như mã này tuân thủ ARC.

Câu hỏi này đã được hỏi nhiều lần và nhiều câu trả lời được đưa ra, nhưng thật đáng buồn là tất cả những câu hỏi được chọn (và một vài câu hỏi khác) đều sai.

Đây là chuỗi thử nghiệm mà tôi đã sử dụng: This is my 123+ test & test2. Got it?!

Đây là các phương thức lớp Cive khách quan của tôi:

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 thực hiện điều này trong Google Toolbox cho Mac . Vì vậy, đó là một nơi tốt để đạt đến đỉnh điểm cách họ làm điều đó. Một tùy chọn khác là bao gồm Hộp công cụ và sử dụng triển khai của chúng.

Kiểm tra việc thực hiện ở đây . (Điều này dẫn đến chính xác những gì mọi người đã đăng ở đây).


0

Đây là cách tôi đang làm điều này trong nhanh chóng.

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

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

-1

// sử dụng phương thức cá thể NSString như thế này:

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

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

hãy nhớ rằng, bạn chỉ nên thực hiện mã hóa hoặc giải mã cho giá trị tham số của mình, không phải tất cả các url bạn yêu cầu.


2
chuỗiByReplatePercentEscapeUSEencoding: chỉ thoát & và = :-(
Sébastien Stormacq

1
Đúng, vì vậy những thứ như + không được mã hóa, khi chúng cần. Vì vậy, đừng sử dụng câu trả lời trên
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 );
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.