iOS URL编码和URL拼接(如含中文等特殊符号).md

  • URL编码默认使用的字符集是US-ASCII.对于非ASCII字符, 需要使用ASCII字符集的超级进行编码.
  • URL中只允许包含4种字符:
英文字符 : a-zA-Z
数字: 0-9
-_.~ 4个特殊字符.
保留字符: ! * ' ( ) ; : @ & = + $ , / ? # [ ]

URL编码使用%其后跟随两位(中文是三位)的十六进制数来替换非ASCII字符,
不能在URL中包含任何非ASCII字符, 如中文字符等.

基本的NSURL

NSString *urlString = @"https://www.baidu.com";
NSURL *url = [NSURL URLWithString:urlString];

但是, 若urlString中含有中文等非URL允许的字符时, 创建的NSURL对象为nil.

iOS 7之后: stringByAddingPercentEncodingWithAllowedCharacters

NSString *latestUrl = @"https://www.baidu.com?name=小明&age=20";

latestUrl = [[latestUrl copy] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

///https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20

NSString *originUrlString = @"https://www.baidu.com/百度?name=小明&age=20";
NSString *encode_fragment = [[originUrlString copy] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSCharacterSet *encode_fragment_invertedSet = [NSCharacterSet URLQueryAllowedCharacterSet].invertedSet;
NSString *encode_fragment_invertedString = [[originUrlString copy] stringByAddingPercentEncodingWithAllowedCharacters:encode_fragment_invertedSet];
/**
 encode_fragment:
 https://www.baidu.com/%E7%99%BE%E5%BA%A6?name=%E5%B0%8F%E6%98%8E&age=20
 
 encode_fragment_invertedString
 %68%74%74%70%73%3A%2F%2F%77%77%77%2E%62%61%69%64%75%2E%63%6F%6D%2F%E7%99%BE%E5%BA%A6%3F%6E%61%6D%65%3D%E5%B0%8F%E6%98%8E%26%61%67%65%3D%32%30
 */

/**

 URLFragmentAllowedCharacterSet  "#%<>[\]^`{|}

 URLHostAllowedCharacterSet      "#%/<>?@\^`{|}

 URLPasswordAllowedCharacterSet  "#%/:<>?@[\]^`{|}

 URLPathAllowedCharacterSet      "#%;<>?[\]^`{|}

 URLQueryAllowedCharacterSet     "#%<>[\]^`{|}

 URLUserAllowedCharacterSet      "#%/:<>?@[\]^`

 */

///自定义的字符集. 如(带空格): [NSCharacterSet characterSetWithCharactersInString:@"#%/!*'\"();:@&=+$,[]? "]

NSString *latestUrl_2 = @"https://www.baidu.com?name=小明&age=20";

NSCharacterSet *defaultCharacterSet = [NSCharacterSet characterSetWithCharactersInString:@"?&=/ "];

if (defaultCharacterSet) {

    NSString *latestUrl_2_defaultAllow = [[latestUrl_2 copy] stringByAddingPercentEncodingWithAllowedCharacters:defaultCharacterSet];

    /**

     %68%74%74%70%73%3A//%77%77%77%2E%62%61%69%64%75%2E%63%6F%6D?%6E%61%6D%65=%E5%B0%8F%E6%98%8E&%61%67%65=%32%30

     可以看出除了?&=/ ,其他字符都被编码了.

     */



    //invertSet

    NSCharacterSet *invertCharacterSet = defaultCharacterSet.invertedSet;

    latestUrl_2 = [[latestUrl_2 copy] stringByAddingPercentEncodingWithAllowedCharacters:invertCharacterSet];

    /**

     https:%2F%2Fwww.baidu.com%3Fname%3D%E5%B0%8F%E6%98%8E%26age%3D20

     */

}

/// 服务端会对请求进行UTF-8解码一次,请确保请求中的字符只进行一次UTF-8编码。


URL中含有中文并且拼接额外参数

NSString *originUrlString = @"https://www.baidu.com?name=小明&age=20";





//需要拼接的参数:转为通过&拼接

NSMutableDictionary *urlParamsDic = [NSMutableDictionary dictionary];

[urlParamsDic setValue:@"22" forKey:@"sex"];

[urlParamsDic setValue:@"one" forKey:@"class"];

__block NSMutableString *joinStr = [NSMutableString string];

if (urlParamsDic && [urlParamsDic isKindOfClass:[NSDictionary class]] && urlParamsDic.count) {

    

    [urlParamsDic enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {

        if (key && obj) {

            [joinStr appendFormat:@"%@=%@&",key,obj];

        }

    }];

    if ([joinStr hasSuffix:@"&"]) {

        [joinStr deleteCharactersInRange:NSMakeRange(joinStr.length-1, 1)];

    }

}

///joinStr = sex=22&class=one



/**

 *url中含有中文,先对其encode生成NSURL

 * 拼接后再decode,最后再对拼接后的encode

 */

//1.encode生成NSURL

NSURL *originUrl = [NSURL URLWithString:[originUrlString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];

///originUrl = https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20

//2.在url后拼接参数

NSString *latestURLString = @"";

BOOL cointainQuery = NO;

if (joinStr.length == 0 || [originUrl.query rangeOfString:joinStr].location != NSNotFound) {

    //其中,若joinStr = 0则表示默认包含该空字符串

    cointainQuery = YES;///

}



if (cointainQuery) {

    latestURLString = originUrl.absoluteString;

}else{

    ///originUrl.query: name=%E5%B0%8F%E6%98%8E&age=20

    if (originUrl.query.length>0) {

        latestURLString = [NSString stringWithFormat:@"%@&%@", originUrl.absoluteString,joinStr];

        ///https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20&sex=22&class=one

    }else{

        BOOL hasSuffix = [originUrl.absoluteString hasSuffix:@"?"];

        latestURLString = [NSString stringWithFormat:@"%@%@%@",originUrl.absoluteString, hasSuffix ? @"":@"?", joinStr];

    }

}

///

//3.拼接后decode

latestURLString = [latestURLString stringByRemovingPercentEncoding];

///latestURLString = https://www.baidu.com?name=小明&age=20&sex=22&class=one

///

//4.最后对对接后的encode

latestURLString =  [latestURLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];

///latestURLString =https://www.baidu.com?name=%E5%B0%8F%E6%98%8E&age=20&sex=22&class=one

NSLog(@"%@",latestURLString);


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,558评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,002评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,024评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,144评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,255评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,295评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,068评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,478评论 1 305
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,789评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,965评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,649评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,267评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,982评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,800评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,847评论 2 351

推荐阅读更多精彩内容