URL 編碼:stringByAddingPercentEscapesUsingEncoding 和stringByAddingPercentEncodingWithAllowedCharacters

URL編碼問題,這個(gè)文章不錯(cuò):

別再使用stringByAddingPercentEscapesUsingEncoding

當(dāng)遇到發(fā)送網(wǎng)絡(luò)請求的參數(shù)中有漢字的情況,很多人一股腦地使用stringByAddingPercentEscapesUsingEncoding:進(jìn)行轉(zhuǎn)義,這樣帶有漢字的urlString就會將每個(gè)漢字轉(zhuǎn)成相應(yīng)的unicode編碼對應(yīng)的3個(gè)%形式,這叫urlEncode(每個(gè)能寫后端的語言都有的方法),但是蘋果的stringByAddingPercentEscapesUsingEncoding:卻不是urlEncode。實(shí)際上我們使用的參數(shù)值可能會包含一些特殊的字符,如&,?這樣的字符,而Percent轉(zhuǎn)義已經(jīng)不能滿足需求了,如下面的例子:

NSString *queryWord = @"漢字&ss";
NSString *urlString = [NSString stringWithFormat:@"https://www.baidu.com/s?ie=UTF-8&wd=%@", queryWord];
NSString *escapedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", escapedString); // https://www.baidu.com/s?ie=UTF-8&wd=%E6%B1%89%E5%AD%97&ss

這是一個(gè)非常常見的情景,(之前公司項(xiàng)目的搜索中,也遇到過這種情況),這種被轉(zhuǎn)義之后的URL,服務(wù)端接收到的參數(shù)會使這樣的

["ie":"UTF-8", "wd":"漢字", "ss":nil]
即使你做如下的改進(jìn):(在請求之前將每個(gè)參數(shù)都轉(zhuǎn)義,再使用&拼接參數(shù)也無濟(jì)于事)

NSString *queryWord = @"漢字&ss";
NSString *escapedQueryWord = [queryWord stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *urlString = [NSString stringWithFormat:@"https://www.baidu.com/s?ie=UTF-8&wd=%@", escapedQueryWord];
NSLog(@"%@", urlString); // https://www.baidu.com/s?ie=UTF-8&wd=%E6%B1%89%E5%AD%97&ss

產(chǎn)生這種情況的原因是:百分號轉(zhuǎn)義不等于URLEncode
該編碼不同于URL編碼,由于不會對&字符編碼,因此不會改變URL參數(shù)的分隔。URL編碼會編碼&、?與其他標(biāo)點(diǎn)符號。如果查詢字符串包含了這些字符,那么需要實(shí)現(xiàn)一種更加徹底的編碼方法。

不過還好iOS7.0推出了stringByAddingPercentEncodingWithAllowedCharacters:方法

這個(gè)方法會對字符串進(jìn)行更徹底的轉(zhuǎn)義,但是需要傳遞一個(gè)參數(shù):這個(gè)參數(shù)是一個(gè)字符集,表示:在進(jìn)行轉(zhuǎn)義過程中,不會對這個(gè)字符集中包含的字符進(jìn)行轉(zhuǎn)義,而保持原樣保留下來。
這樣就可以使用它改造上面的代碼了:

NSString *queryWord = @"漢字&ss";
NSString *escapedQueryWord = [queryWord stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet letterCharacterSet]];
NSLog(@"%@", escapedQueryWord); // %E6%B1%89%E5%AD%97%26ss
NSString *urlString = [NSString stringWithFormat:@"https://www.baidu.com/s?ie=UTF-8&wd=%@", escapedQueryWord];
NSLog(@"%@", urlString); // https://www.baidu.com/s?ie=UTF-8&wd=%E6%B1%89%E5%AD%97%26ss

在上面的例子中傳遞參數(shù)[NSCharacterSet letterCharacterSet]來保證字母不被轉(zhuǎn)義。所以被轉(zhuǎn)義之后的參數(shù)值是:%E6%B1%89%E5%AD%97%26ss,這樣問題就解決了,但是有時(shí)候會遇到queryString中的表單域也需要轉(zhuǎn)義的情況,比如是一個(gè)表單數(shù)組如:

https://www.baidu.com/s?person[contact]=13801001234&person[address]=北京&habit[]=游泳&habit[]=騎行

這樣可以使用將key轉(zhuǎn)義,不過key中的[和]字符是不需要轉(zhuǎn)義的:可以自定義一個(gè)CharacterSet實(shí)現(xiàn)需求:

NSMutableCharacterSet *mutableCharSet = [[NSMutableCharacterSet alloc] init];
[mutableCharSet addCharactersInString:@"[]"]; // 允許'['和']'不被轉(zhuǎn)義
NSCharacterSet *charSet = mutableCharSet.copy;

NSMutableString *mutableString = [NSMutableString string];
for (unit in queryString) {
    NSString *escapedField = [unit.field stringByAddingPercentEncodingWithAllowedCharacters:charSet];
    NSString *escapedValue = [unit.value stringByAddingPercentEncodingWithAllowedCharacters:charSet];
    [mutableString addFormat:@"%@=%@", escapedField, escapedValue];
}

這樣問題已經(jīng)圓滿解決了,美中不足的是:當(dāng)queryString非常多的時(shí)候你如何保證從queryString正確地提取出來每個(gè)unit呢,這個(gè)牽扯到復(fù)雜的字符串解析的問題。先不做討論。

下面還有對AFN的分析,就不貼了.
http://www.cnblogs.com/Mike-zh/p/5152073.html

URL編碼:

 NSCharacterSet *allowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:urlStr]invertedSet];//非URLstr字符集
    
    NSString *encodedUrl = [urlStr stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];//對非URLstr字符集編碼
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 別再使用stringByAddingPercentEscapesUsingEncoding 當(dāng)遇到發(fā)送網(wǎng)絡(luò)請求的參...
    怎樣m閱讀 1,955評論 0 1
  • 編碼問題一直困擾著開發(fā)人員,尤其在 Java 中更加明顯,因?yàn)?Java 是跨平臺語言,不同平臺之間編碼之間的切換...
    x360閱讀 2,579評論 1 20
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評論 19 139
  • AFNetworking2.0源碼解析<一> AFNetworking2.0源碼解析<二>-- 構(gòu)建普通請求: 格...
    錢噓噓閱讀 1,849評論 0 4
  • 首先,先聊一聊2016年發(fā)生的部分八卦和熱點(diǎn)新聞: 快播案、山東育苗事件、王寶強(qiáng)事件、林丹出軌、劉愷威出軌、張靚穎...
    暢談一下閱讀 887評論 0 0

友情鏈接更多精彩內(nèi)容